Languages often provide shortcuts for common functions, sometimes called “syntactic sugar” – a reference to how they “sweeten” the syntax and make code easier to code or read. Today, we’re going to take a look at three shortcuts that involve the question mark (?).
The ?? operator, introduced in Visual Studio 2005, is a null coalescing operator that will return the first non-null operand in a sequence. Consider the following expression:
x = a ?? b ?? c ?? d;
If a is non-null, then it is returned; if a is null and b is not null, then b is returned; and so forth. The ?? operator is actually binary – this expression is really ((a ?? b) ?? c) ?? d.
Internally, when the ?? operator is compiled into Common Intermediate Language, it is translated into the ? … : conditional operator. So x = a ?? b becomes:
x = a.HasValue() ? a : b;
The ? … : operator is a handy shortcut for an if statement and is the equivalent of the Visual Basic If operator. (If was introduced in Visual Studio 2008. The Iif function is also available, but it lacks short-circuiting). The syntax is:
condition ? value_if_true : value_if_false;
If the condition is true, then the left value is evaluated and returned; if it is false, then the right value is evaluated and returned. There are at least three important points here. One, unlike Iif in VB, only one of the expressions is evaluated. So we’re not going to reformat your hard drive here:
(1 == 2) ? FormatCDrive() : DoSomethingUseful();
The second important point is that in C#, unlike in C++, the ? … : operator is not valid by itself. You can pass its return value to a function, you can return its value, or you can set a variable equal to its value, but the above statement containing only the ? … : operator and its operands is not a legal C# statement.
The third important point is that strictly speaking, this operator is not a shortcut for an if statement. Though functionally it behaves as an if statement, it does actually get compiled to different CIL.
The final shorthand we will consider is the ? shorthand for Nullable. The Nullable template class allows scalar types like int and DateTime to have null values. These two statements are equivalent?
Nullable<int> i = 5;
int? j = 5;
In both cases, i and j are “nullable” types, meaning that they can receive null as their value, allowing the programmer to distinguish between zero and not set.
Photo credit: Adam Ciesielski