Objective-C and C#: Brothers From Another Mother
My colleague Paul Irwin just posted an article called Translating Objective-C to C# – Part 1 of n. I think it’s an excellent synopsis. Having myself spent nearly a year and a half doing Objective-C programming part time before learning to C#, this is a topic that hits home for me. There are a couple of areas that warrant some additional clarification, as they are obscure for most Objective-C and .NET programmers alike.
What is id?
To answer that, we must go back to the future: to 1986. Just kidding. Well, not really. Obj-C started life in the early 1980’s, originating as a C preprocessor that allowed programmers to create purely OOP C software in a manner very much inspired by Smalltalk (just like C# was). It eventually added a runtime, then deeper compiler extensions, but interestingly, not a standard library. Obj-C is a superset of C, and gets compiled down to C. Obj-C types must, at the end of the day, be composed of C types. Since C has no object-y primitive type itself, Obj-C needs to create one. And it does, it’s a struct called objc_object
. Unlike C#, all Obj-C objects live on the heap. Instead of requiring users to write (objc_object *) all over the place, the designers mercifully declared id
as alias to objc_object*
. The actual C code for the definition of id
is:
typedef struct objc_class *Class; typedef struct objc_object { Class isa; } *id;
Interestingly, the familiar NSObject
root class has only one internal field: Class isa
. When you write a line of Obj-C like [NSObject alloc]
, the compiler emits a C call to the runtime’s id class_createInstance(Class cls, size_t extraBytes)
function. Notice, though, how neither that function nor id
is coupled to NSObject
.
As mentioned above, Obj-C does not have an “official” standard library, so it’s possible to use Obj-C without using Apple’s standard library, called Cocoa. In fact, you could just use the standard C library and create your own Object
class, and id
will still work with the runtime. gcc
even comes with the Object
class, which you can use as your root object class instead. Of course, that way lies madness.
C#/.NET works the other way around. It instead of reducing OOP (Obj-C) code down to procedural code (C), it reduces OOP code (C#) down to CIL bytecode which is OOP from the get go, with instructions like initobj
and isinst
. Even primitive types are all objects–yet primitive C# value types still live in the stack just like in C and Obj-C. But that is not a language feature of C#, it’s a feature of the CLS itself. In Obj-C, that all has to be handled by whatever facilities C has, which means using pointers and using malloc. id
is actually quite clever, and is probably closest to something like .NET’s TypedReference
struct which plays a big role under the covers there too:
String str = "My String"; TypedReference strId; strId = __makeref(str); Console.WriteLine(__reftype(strId).FullName); // outputs "System.String" String result = __refvalue(strId, string); Console.WriteLine(result); // outputs "My String"
nil vs. null
Strictly speaking nil
is the value of an id
variable set to 0
. In the bigger picture, however, nil
is an implementation of the null object pattern. C#, as noted, lacks a direct equivalent, but if it did, it would probably be referenced by calling a hypothetical static field called System.Object.Null
which would return an instance of:
public class NullObject { public new String ToString() { return String.Empty; } public new Int32 GetHashCode() { return 0; } public new Boolean Equals(Object other) { return other.GetType() == this.GetType(); } }
The biggest difference between Obj-C’s nil
object and the null keyword in C# is that in Obj-C, it is perfectly permissible to send messages to nil
. The result will usually be 0
/nil
, instead of the runtime raising a NullReferenceException
as it does in C#.
More Smalltalk
What’s most exciting to me is that Objective-C/Cocoa and C#/.NET both share the same parent: Smalltalk. They are more alike than they are different. Shoot, for a couple of years now even Obj-C/c compiles down to an intermediate language that runs JIT-compiled in a virtual machine.
There’s a lot to be excited about, if you’re a fan of language design. I hope more C# developers pickup Objective-C like Paul, and I hope more Objective-C developers pickup C# like me.
Further reading: