The @" syntax in Objective-C vs C#

A common mistake that I see in some of the code from our customers, or from contributed samples to the MonoMac repository is the use of the @"string" syntax in C# programs. Summary: do not use the @"..." when porting Objective-C samples to C#.

String Syntax in Objective-C and C#

Objective-C supports two kinds of string literals in your source code, strings that are surrounded by double-quotes and strings that are prefixed with the at-sign and then double quotes.

The first kind are zero-terminated C-style strings. For example the string "foo" is encoded by the compiler as the following four bytes: 'f', 'o', 'o' and zero plus the address of the string at the location where this is referenced.

The second kind, for example @"Hello World" is a CoreFoundation string, and the compiler has to encode by creating a static instance of a CoreFoundation CFString object: it has a class identifier, some object flags, a pointer to the data ('foo' in this case) and the length of the string.

In both the c-string style and the CFString style, escape sequences are processed by the compiler. This means that if you use "1\n2" or @"1\n2" this will produce in both cases a string consisting of the '1' character followed by a newline (byte value 10) and the '2' character.

In C# the syntax @"string" does not mean "encode as a CFString" object. Instead it is a quoted-string literal, and it instructs the compiler to avoid performing escape sequence processing. In C# the strings "1\n2" and @"1\n2" have respectively lengths 3 and 4. The former one consists of the characters '1', newline (byte value 10) and character '2'. While the latter consists of the characters '1', '\', 'n' and '2'.

System.String vs Foundation.NSString in MonoMac/MonoTouch

In the MonoTouch/MonoMac binding strings are almost always exposed in the binding with the native C# string type (System.String). Any conversions between the C# string and the Objective-C string type are done by the runtime.

There are a handful of places where we must expose NSString values instead of strings. This is usually necessary when the underlying Objective-C code performs reference comparisons instead of content comparisons for strings. Some Objective-C APIs for example use these strings as special "tokens" that you must pass verbatim in your application to a method.

We typically use those for notification names, keys in dictionaries and a handful of other places. You will notice in those handful of cases that Mono's API's expose an NSString parameter or return value instead of a string parameter or return value.

For example if you have a AddNotification (NSString key) API, you would typically use it like this:

	// example class exposing a notificatin as an NSString:
	// class SomeClass {
	//        NSString WakeUpNotification { get; }
	// }
	
	AddNotification (SomeClass.WakeUpNotification);

Conversions

Converting from a C# string to an NSString is easy, all you have to do is call new NSString ("mystring").

To go the other way around from an NSString to a string, you can either use an explicit cast (this is the recommended design pattern from the Framework Design Guidelines) or you can use the ToString () method on an NSString.

Posted on 14 Dec 2010 by Miguel de Icaza
This is a personal web page. Things said here do not represent the position of my employer.