tags:

views:

3228

answers:

9

I've recently purchased a Mac and use it primarily for C# development under VMWare Fusion. With all the nice Mac applications around I've started thinking about Xcode lurking just an install click away, and learning Objective-C.

The syntax between the two languages looks very different, presumably because Objective-C has its origins in C and C# has its origins in Java/C++. But different syntaxes can be learnt so that should be OK.

My main concern is working with the language and if it will help to produce well-structured, readable and elegant code. I really enjoy features such as LINQ and var in C# and wonder if there are equivalents or better/different features in Objective-C.

What language features will I miss developing with Objective-C? What features will I gain?

Edit: The framework comparisons are useful and interesting but a language comparison are what this question is really asking (partly my fault for originally tagging with .net). Presumably both Cocoa and .NET are very rich frameworks in their own right and both have their purpose, one targeting Mac OS X and the other Windows.

Thank you for the well thought out and reasonably balanced viewpoints so far!

+3  A: 

One thing I love about objective-c is that the object system is based on messages, it lets you do really nice things you couldn't do in C# (at least not until they support the dynamic keyword!).

Another great thing about writing cocoa apps is Interface Builder, it's a lot nicer than the forms designer in Visual Studio.

The things about obj-c that annoy me (as a C# developer) are the fact that you have to manage your own memory (there's garbage collection, but that doesn't work on the iPhone) and that it can be very verbose because of the selector syntax and all the [ ].

jonnii
`dynamic` will only get you halfway - implementing a true dynamic object, even with trivial things such as message delegation, is tedious even in C# 4.0. On the other hand, the price for flexibility true dynamic message passing a la ObjC is lost type safety.
Pavel Minaev
It's worth pointing out that Objective-C allows for opt-in static typing, which does provide a much greater degree of type safety. Some people prefer compile-time checking, others prefer runtime checking. The nice thing (in both languages) is that the choice need not be absolute.
Quinn Taylor
Windows Forms designer is not so great, but if you are able to use WPF (as of .NET 3.0) Expression Blend is hard to beat...
Nate Bross
A: 

The method calls used in o-c make for easily read code, in my opinion much more elegant than c# and o-c is built on top of c so all c code should work fine in 0-c. The big seller for me though is that o-c is an open standard so you can find compilers for any system.

e.kite.0
ISO C# is also an open standard. Also, so far as I know, the only ObjC compiler in existence is gcc.
Pavel Minaev
@Pavel: There's also the Portable Object Compiler (http://users.telenet.be/stes/compiler.html) and clang.
mipadi
Actually, GCC is no longer the only compiler — Clang and LLVM are a pair of technologies designed and developed to replace GCC and do things it never could, including JIT compilation. This is at the core of OpenCL in Snow Leopard. They're also extensible to other languages, and are worth checking out.
Quinn Taylor
I honestly wouldn't consider portability to be a pro of Objective-C. Rather, the strengths are more along the lines of rapid development and reduced volume of code to accomplish the same task.
Quinn Taylor
Thanks for correcting my mistake on compiler availability. Well, portability is technically there anyway - I can use MinGW/ObjC on Win32 just fine, for example - in that sense it's just as portable as gcc itself is. Of course, the libraries won't be there (though... is there GnuStep/Win32?), but this situation isn't really much worse than what we have with Mono; so on the whole, I'd say that portability isn't a strong point for either side.
Pavel Minaev
C# can be compiled with the open source Mono project.
Alex Angas
+1  A: 

Here's a pretty good article comparing the two languages: http://www.coderetard.com/2008/03/16/c-vs-objective-c/

Cinder6
It's a pity the page claims to be in UTF-8 but has all sorts of nasty replacements for apostrophes and quote marks. I think his text uses "curvy" quotes, but they sure garble the code...
Quinn Taylor
they appear to have stolen their intro whole hog, but even the source article has their code munged. neither is a particularly great article.
dnord
+25  A: 

No language is perfect for all tasks, and Objective-C is no exception, but there are some very specific niceties. Like using LINQ and var (for which I'm not aware of a direct replacement), some of these are strictly language-related, and others are framework-related.

(NOTE: Just as C# is tightly coupled with .NET, Objective-C is tightly coupled with Cocoa. Hence, some of my points may seem unrelated to Objective-C, but Objective-C without Cocoa is akin to C# without .NET / WPF / LINQ, running under Mono, etc. It's just not the way things are usually done.)

I won't pretend to fully elaborate the differences, pros, and cons, but here are some that jump to mind.

  • One of the best parts of Objective-C is the dynamic nature — rather than calling methods, you send messages, which the runtime routes dynamically. Combined (judiciously) with dynamic typing, this can make a lot of powerful patterns simpler or even trivial to implement.

  • As a strict superset of C, Objective-C trusts that you know what you're doing. Unlike the managed and/or typesafe approach of languages like C# and Java, Objective-C lets you do what you want and experience the consequences. Obviously this can be dangerous at times, but the fact that the language doesn't actively prevent you from doing most things is quite powerful. (EDIT: I should clarify that C# also has "unsafe" features and functionality, but they default behavior is managed code, which you have to explicitly opt out of. By comparison, Java only allows for typesafe code, and never exposes raw pointers in the way that C and others do.)

  • Categories (adding/modifying methods on a class without subclassing or having access to source) is an awesome double-edged sword. It can vastly simplify inheritance hierarchies and eliminate code, but if you do something strange, the results can sometimes be baffling.

  • Cocoa makes creating GUI apps much simpler in many ways, but you do have to wrap your head around the paradigm. MVC design is pervasive in Cocoa, and patterns such as delegates, notifications, and multi-threaded GUI apps are well-suited to Objective-C.

  • Cocoa bindings and key-value observing can eliminate tons of glue code, and the Cocoa frameworks leverage this extensively. Objective-C's dynamic dispatch works hand-in-hand with this, so the type of the object doesn't matter as long as it's key-value compliant.

  • You will likely miss generics and namespaces, and they have their benefits, but in the Objective-C mindset and paradigm, they would be niceties rather than necessities. (Generics are all about type safety and avoiding casting, but dynamic typing in Objective-C makes this essentially an non-issue. Namespaces would be nice if done well, but it's simple enough to avoid conflicts that the cost arguably outweighs the benefits, especially for legacy code.)

  • For concurrency, Blocks (a new language feature in Snow Leopard, and implemented in scores of Cocoa APIs) are extremely useful. A few lines (frequently coupled with Grand Central Dispatch, which is part of libsystem on 10.6) can eliminates significant boilerplate of callback functions, context, etc. (Blocks can also be used in C and C++, and could certainly be added to C#, which would be awesome.)

Quinn Taylor
Technically, C# has all non-type-safe power features that ObjC does: raw pointers, pointer arithmetic, bound-unchecked arrays, unions, `alloca`. It just doesn't make them as readily accessible - you need to opt in explicitly.
Pavel Minaev
Also, your points on Cocoa are obviously applicable to Cocoa, rather than ObjC (there are other language bindings for Cocoa). It's also not clear what you're comparing Cocoa against - for example, WPF has everything you list as well.
Pavel Minaev
I simply mention Cocoa because most of the appeal of programming in Objective-C is due to the Cocoa frameworks. Would C# be interesting without .NET and/or WPF? The asker specifically mentioned LINQ, so he's obviously looking beyond the language, to the experience.
Quinn Taylor
LINQ is a part of C#-the-language in a sense that the language has direct support for LINQ constructs (which makes it so much easier to use in some complicated nesting cases).
Pavel Minaev
Which is fine. I'm not trying to pick a fight with C#. If I had to write Windows software, that's what I'd use. I'm merely trying to point out similarities and differences between the languages and related tools. You're very obviously more experienced with C#, and I with Objective-C. I appreciate your clarifications, but perhaps more constructive answers and less hair-splitting will be most useful.
Quinn Taylor
It's not hair-splitting, Quinn. I merely pointed out that what started as a language comparison turned into general discussion of how Cocoa is good at some point in your reply. I would still like to point out that your points on Cocoa are not _comparisons_ - they say "it does X well" - and it may well be the case - but they don't say "it does X better/worse than C#+WPF", which is what the question is broadly about.
Pavel Minaev
That's mainly because I'm not familiar enough with the C# alternatives. Unlike .NET, it's almost always the case that Cocoa code is Objective-C code, which is why I said it's hair-splitting. (I would imagine that C# people assume .NET and consider environments like Mono the exception rather than the rule, and it's the same on the other side of the fence.) With that in mind, see if I haven't addressed the asker's final question, in bold...
Quinn Taylor
Regarding new additions to your answer: ObjC blocks are just first-class anonymous functions, right? If so, C# has them (as anonymous delegates and lambdas). Their use specifically in concurrency context is coming in .NET 4.0 - Parallel LINQ. Java has anonymous inner classes, which can serve in that role too, though they don't capture mutable locals, and are extremely verbose for such a construct.
Pavel Minaev
That's a good question — Blocks are closures, but I don't know how close they are to their C# cousins. All in all, they sound pretty close. (They're certainly not the same as anonymous inner classes in Java.) Blocks capture surrounding scope (including relevant local variables) and are automatically copied to the heap as necessary. They can be treated as similar to anonymous functions, but there are some subtle differences. One of the biggest differences, obviously, is the ability to dispatch blocks with GCD.
Quinn Taylor
+1 excellent answer Quinn
h4xxr
+1  A: 

No technical review here, but I just find Objective-C much less readable. Given the example Cinder6 gave you:

C#

List<string> strings = new List<string>();
strings.Add("xyzzy"); // takes only strings
strings.Add(15); // compiler error
string x = strings[0]; // guaranteed to be a string
// or non-existant (yielding an exception)
strings.RemoveAt(0);

Objective-C

NSMutableArray *strings = [[NSArray array] mutableCopy];
[strings addObject:@"xyzzy"];
[strings addObject:[NSNumber numberWithInt:15]];
string x = [strings objectAtIndex:0];
[strings removeObjectAtIndex:0];

It looks awful. I even tried reading 2 books on it, they lost me early on, and normally I don't get that with programming books / languages.

I'm glad we have Mono for Mac OS, because if I'd had to rely on Apple to give me a good development environment...

TimothyP
Ignoring the fact that the 1st line should end with `[NSMutableArray array]` instead (he's leaking memory) and the 4th line should start with `NSString* x` or `id x` (compile error)... Yes, Objective-C lacks generics (I honestly don't miss them), you don't index objects with array syntax, and the APIs are generally more verbose. To-may-to, to-mah-to. It really comes down to what you prefer to see. (You could write the same code in C++ STL and I'd think it was hideous.) To me, readable code often means the text of the code tells you what it's doing, and thus the Objective-C code is preferable.
Quinn Taylor
I don't really find anything wrong with syntax as such - the main reason why it _feels_ less readable is because 1) it's unfamiliar to everyone coming from C background, and 2) it is used in the middle of plain C constructs, where it looks alien. On the other hand, Smalltalkish named-parameters-as-part-of-method-name actually make calls more understandable from the get go. In fact, your C# code sample demonstrates this well - it won't compile, because `List<T>.Remove` takes a _string_ as an argument, and removes first occurenceof that string. To remove by index, you need `RemoveAt`.
Pavel Minaev
... whereas ObjC version with `removeObjectAtIndex:`, while more verbose, is also unambiguous as to what it does.
Pavel Minaev
Excellent points, Pavel. Also, the inconsistency between `strings[0]` and `strings.RemoveAt(0)` detracts from the clarity, at least for me. (Also, it always bugs me when method names begin with a capital letter... I know it's a minor niggle, but it's just weird.)
Quinn Taylor
On the other hand, `strings[0]` is consistent with plain arrays, and can be used on the left side of the assignment operator.
Pavel Minaev
True enough. Personal preference again, but I would hate syntax that masks methods with array notation. Perhaps that's because I also use plain C arrays on occasion, and mixing notation would harm code comprehension more than it helps.
Quinn Taylor
I would like to note, none of the code samples are mine, they are taken from the page someone linked to earlier :p
TimothyP
A: 

Probably most important difference is memory management. With C# you get garbage collection, by virtue of it being a CLR based language. With Objective-C you need to manage memory yourself.

If you're coming from a C# background (or any modern language for that matter), moving to a language without automatic memory management will be really painful, as you will spend a lot of your coding time on properly managing memory (and debugging as well).

DSO
ObjC has tracing garbage collection these days. On the other hand, C# lets you manage memory yourself if you want (thanks to raw pointers).
Pavel Minaev
I don't find manual memory management in Objective-C (in the context of Apple's frameworks) to be a much of a burden: the retain/release/autorelease cycle is much less cumbersome than "traditional" memory management in C and C++.
mipadi
This just isn't true DSO - even on a non-garbage-collection environment like iPhone, the retain/release and autorelease stuff takes about 10 minutes to learn and then its no a problem. I've found a lot of C#-ers that like to exaggerate the challenges of memory management. It's almost like they fear they'd start liking obj-c too much otherwise... ;)
h4xxr
The basics of manual memory management isn't hard. But it can get complicated real quick when you start passing allocated objects around and need to deal with complex object graphs, because you need to carefully follow rules as who is responsible for freeing and when. Reference counting implementations make it somewhat easier, except you need to deal with cycles in object graphs... compared to C#, all of this IMO is a big difference.
DSO
+1  A: 

Other than the paradigm difference between the 2 languages, there's not a lot of difference. As much as I hate to say it, you can do the same kind of things (probably not as easily) with .NET and C# as you can with Objective-C and Cocoa. As of Leopard, Objective-C 2.0 has garbage collection, so you don't have to manage memory yourself unless you want to (code compatibility with older Macs and iPhone apps are 2 reasons to want to).

As far as structured, readable code is concerned, much of the burden there lies with the programmer, as with any other language. However, I find that the message passing paradigm lends itself well to readable code provided you name your functions/methods appropriately (again, just like any other language).

I'll be the first to admit that I'm not very familiar with C# or .NET. But the reasons Quinn listed above are quite a few reasons that I don't care to become so.

alesplin
+3  A: 

Manual memory management is something beginners to Objective-C seems to have most problem with, mostly because they think it is more complex than it is.

Objective-C and Cocoa by extension relies on conventions over enforcement; know and follow a very small set of rules and you get allot for free by the dynamic run-time in return.

The not 100% true rule, but good enough for everyday is:

  • Every call to alloc should be matched with a release at the end of the current scope.
  • If the return value for your method has been obtained by alloc then it should be returned by return [value autorelease]; instead of being matched by a release.
  • Use properties, and there is no rule three.

The longer explanation follows.

Memory management is based on ownership; only the owner of an object instance should ever release the object, everybody else should always do nothing. This mean that in 95% of all code you treat Objective-C as if it was garbage collected.

So what about the other 5%? You have three methods to look out for, any object instance received from these method are owned by the current method scope:

  • alloc
  • Any method beginning with the word new, such as new or newService.
  • Any method containing the word copy, such as copy and mutableCopy.

The method have three possible options as of what to do with it's owned object instances before it exits:

  • Release it using release if it is no longer needed.
  • Give ownership to the a field (instance variable), or a global variable by simply assigning it.
  • Relinquish ownership but give someone else a chance to take ownership before the instance goes away by calling autorelease.

So when should you pro-actively take ownership by calling retain? Two cases:

  • When assigning fields in your initializers.
  • When manually implementing setter method.
PeyloW
+1 Excellent summary. Sounds very similar to when I learnt C years ago.
Alex Angas
+1  A: 

As a programmer just getting started with Objective-C for iPhone, coming from C# 4.0, I'm missing lambda expressions, and in particular, Linq-to-XML. The lambda expressions are C#-specific, while the Linq-to-XML is really more of a .NET vs. Cocoa contrast. In a sample app I was writing, I had some XML in a string. I wanted to parse the elements of that XML into a collection of objects.

To accomplish this in Objective-C/Cocoa, I had to use the NSXmlParser class. This class relies on another object which implements the NSXMLParserDelegate protocol with methods that are called (read: messages sent) when an element open tag is read, when some data is read (usually inside the element), and when some element end tag is read. You have to keep track of the parsing status and state. And I honestly have no idea what happens if the XML is invalid. It's great for getting down to the details and optimize performance, but oh man, that's a whole lot of code.

By contrast, here's the code in C#:

using System.Linq.Xml;
XDocument doc = XDocument.Load(xmlString);
IEnumerable<MyCustomObject> objects = doc.Descendants().Select(
         d => new MyCustomObject{ Name = d.Value});

And that's it, you've got a collection of custom objects drawn from XML. If you wanted to filter those elements by value, or only to those that contain a specific attribute, or if you just wanted the first 5, or to skip the first 1 and get the next 3, or just find out if any elements were returned... BAM, all right there in the same line of code.

There are many open-source classes that make this processing a lot easier in Objective-C, so that does much of the heavy lifting. It's just not this built in.

*NOTE: I didn't actually compile the code above, it's just meant as an example to illustrate the relative lack of verbosity required by C#.

lividsquirrel