Objective-C 与 C # 相比如何?

我最近购买了一台 Mac,主要用于 VMWare Fusion 下的 C # 开发。有了这么多不错的 Mac 应用程序,我开始考虑只需要点击一下安装就可以使用 Xcode,并学习 Objective-C。

这两种语言之间的语法看起来非常不同,大概是因为 Objective-C 起源于 C,而 C # 起源于 Java/C + + 。但是可以学习不同的语法,所以应该没问题。

我主要关心的是如何使用这种语言,以及它是否有助于产生结构良好、可读和优雅的代码。我真的很喜欢 C # 中的 LINQ 和 var 这样的特性,并且想知道 Objective-C 中是否有对等的或者更好/不同的特性。

我会错过用 Objective-C 开发哪些语言特性? 我会获得哪些特性?

编辑: 框架比较是有用和有趣的,但是 语言比较才是这个问题真正要问的(部分原因是我最初使用 .net标记)。据推测,可可和。NET 本身就是非常丰富的框架,两者都有自己的目标,一个针对 Mac OS X,另一个针对 Windows。

谢谢你到目前为止深思熟虑和合理平衡的观点!

90796 次浏览

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 [ ].

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

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

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 a 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.) NSOperationQueue is also a very convenient way to add concurrency to your own code, by dispatching either custom NSOperation subclasses or anonymous blocks which GCD automatically executes on one or more different threads for you.

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
strings.RemoveAt(0);                   // or non-existant (yielding an exception)

Objective-C

NSMutableArray *strings = [NSMutableArray array];
[strings addObject:@"xyzzy"];
[strings addObject:@15];
NSString *x = strings[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...

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).

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.

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 a lot 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.

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#.

I've been programming in C, C++ and C# now for over 20 years, first started in 1990. I have just decided to have a look at the iPhone development and Xcode and Objective-C. Oh my goodness... all the complaints about Microsoft I take back, I realise now how bad things code have been. Objective-C is over complex compared to what C# does. I have been spoilt with C# and now I appreciate all the hard work Microsoft have put in. Just reading Objective-C with method invokes is difficult to read. C# is elegant in this. That is just my opinion, I hoped that the Apple development language was a good as the Apple products, but dear me, they have a lot to learn from Microsoft. There is no question C#.NET application I can get an application up and running many times faster than XCode Objective-C. Apple should certainly take a leaf out of Microsoft's book here and then we'd have the perfect environment. :-)

Sure, if everything you saw in your life is Objective C, then its syntax looks like the only possible. We could call you a "programming virgin".

But since lots of code is written in C, C++, Java, JavaScript, Pascal and other languages, you'll see that ObjectiveC is different from all of them, but not in a good way. Did they have a reason for this? Let's see other popular languages:

C++ added a lot extras to C, but it changed the original syntax only as much as needed.

C# added a lot extras compared to C++ but it changed only things that were ugly in C++ (like removing the "::" from the interface).

Java changed a lot of things, but it kept the familiar syntax except in parts where the change was needed.

JavaScript is a completely dynamic language that can do many things ObjectiveC can't. Still, its creators didn't invent a new way of calling methods and passing parameters just to be different from the rest of the world.

Visual Basic can pass parameters out of order, just like ObjectiveC. You can name the parameters, but you can also pass them the regular way. Whatever you use, it's normal comma-delimited way that everyone understands. Comma is the usual delimiter, not just in programming languages, but in books, newspapers, and written language in general.

Object Pascal has a different syntax than C, but its syntax is actually EASIER to read for the programmer (maybe not to the computer, but who cares what computer thinks). So maybe they digressed, but at least their result is better.

Python has a different syntax, which is even easier to read (for humans) than Pascal. So when they changed it, making it different, at least they made it better for us programmers.

And then we have ObjectiveC. Adding some improvements to C, but inventing its own interface syntax, method calling, parameter passing and what not. I wonder why didn't they swap + and - so that plus subtracts two numbers. It would have been even cooler.

Steve Jobs screwed up by supporting ObjectiveC. Of course he can't support C#, which is better, but belongs to his worst competitor. So this is a political decision, not a practical one. Technology always suffers when tech decisions are made for political reasons. He should lead the company, which he does good, and leave programming matters to real experts.

I'm sure there would be even more apps for iPhone if he decided to write iOS and support libraries in any other language than ObjectiveC. To everyone except die-hard fans, virgin programmers and Steve Jobs, ObjectiveC looks ridiculous, ugly and repulsive.