How Did I Miss This?
I consider myself relatively savvy in the ways of C#. However, I apparently missed a pretty cool 2.0 operator back in the day and just stumbled over it tonight (by way of researching it after being absolutely sure that the code I was looking at was wrong). At any rate, I'm talking about the null coalescing operator ("??"). Rather than spend more time duplicating what has already been said about it, I'll just point you to R. Aaron Zupancic's post on the topic.
One thing that I do want to point about this technique is that it is a bit more (slightly) than syntactic sugar - as it actually generates different IL than the same task implemented with the ternary operator. For example, here is some typical ternary-based code.
1: private static void SayHello2(string name) { 2: Console.WriteLine(name != null ? name : "Nobody to greet");
3: }
And here is the IL that the compiler produces.
1: .method private hidebysig static void SayHello2(string name) cil managed
2: { 3: // Code size 19 (0x13)
4: .maxstack 8
5: IL_0000: nop
6: IL_0001: ldarg.0
7: IL_0002: brtrue.s IL_000b
8: IL_0004: ldstr "Nobody to greet"
9: IL_0009: br.s IL_000c
10: IL_000b: ldarg.0
11: IL_000c: call void [mscorlib]System.Console::WriteLine(string)
12: IL_0011: nop
13: IL_0012: ret
14: } // end of method Program::SayHello2
Now - consider the same method using the null coalescing operator.
1: private static void SayHello1(string name) { 2: Console.WriteLine(name ?? "Nobody to greet");
3: }
The corresponding IL is as follows.
1: .method private hidebysig static void SayHello1(string name) cil managed
2: { 3: // Code size 18 (0x12)
4: .maxstack 8
5: IL_0000: nop
6: IL_0001: ldarg.0
7: IL_0002: dup
8: IL_0003: brtrue.s IL_000b
9: IL_0005: pop
10: IL_0006: ldstr "Nobody to greet"
11: IL_000b: call void [mscorlib]System.Console::WriteLine(string)
12: IL_0010: nop
13: IL_0011: ret
14: } // end of method Program::SayHello1
So what's the difference here? Practically speaking, the difference between the 2 is that the null coalescing operator results in IL code that duplicates the method argument after it's been loaded onto the stack, and pops it off the stack if the conditional test returns false. In contrast, the ternary operator, rather than duplicating the method argument on the stack, performs an additional load operation to add the duplicate value onto the stack.
Now, does this mean that if you rewrite all your code, replacing ternary null comparisons with the coalescing operator, your code will perform orders of magnitude better?? Not even close. However, I find it interesting that the 2 methods are actually different at the IL level - and if you've read this far, you find it interesting enough!
I am currently the Editor-in-Chief for MSDN Magazine. I joined Microsoft in 2006 as a product planner with the certification team at Microsoft Learning. Prior to that, I spent my career as a developer and later as an architect. My main technology passions include pretty much anything on language theory, agile development, and service-oriented architecture.