Something struck me yesterday. Something Evil. It comes out of the fact that you can use C#’s Null-Coalescing operator – that’s ?? to most people – with reference types as well as nullable (value) types.
Most C# devs I dare say will be familiar with C#’s nullable types. They’re really System.Nullable<T>
but C# allows you to use the nice shortcut of just putting a ? after the type declaration…
class ExampleClass { int? exampleField; System.Nullable<int> isTheSameAsExampleField; }
You quite often see ?? used with examples of nullable types but it can actually be used with any reference type too. String is the most obvious[1]. For instance there’s a very common gotcha of performing some operation on a string that could actually be null. For instance,
if(someObject.someString.Contains("SOME TEXT")) {
If someString is NULL (as opposed to "") this will throw a NullReferenceException
One might use C#’s guaranteed short-circuit evaluation and left-to-right evaluation to get round this
if(someObject.someString != null && someObject.someString.Contains("SOME TEXT")) {
(yes I could also use String.IsNullOrWhiteSpace etc)
But it’s also possible to use the ?? operator
if( (someObject.someString ?? "" ).Contains("SOME TEXT")) {
Note that although the logical result of these two options is the same the way it accomplishes that result is subtly different. In the first example if the string is null the Contains will never be executed. In the second it will be executed against the "" object (which clearly doesn’t contain "SOME TEXT"). The result in both cases is that the if condition as a whole evaluates to false, but it does so for different reasons.
…and so now here’s a way you can use these powers for evil. Let’s say you need to add something to a list, the problem is that you don’t know if the list has been instantiated yet, but if it hasn’t you need to instantiate it. This type of situation actually happens quite a lot and this solution works, ho-hum.
List<string> list = null; ...some code... (list ?? (list = new List<string>()) ).Add("blah");
It works because C#’s assignment operator (single =) produces a result, the result is the value that was assigned. So this code says "if list is instantiated then use it for the Add. If not then instantiate a new List<string> and assign the value to list then take the result of that assignment (the newly instantiated object) and use that for the Add".
In summary then, you can use ?? against any type that could have a null value, not just System.Nullable<T>, but be careful with it because it’s a power than can be easily abused.
[1] string is actually a reference type, but it behaves like a value type
Useful for lazy loading too:
private Action _action;
public Action SomeAction
{
get
{
return _action ?? (_action = new Action(x =>
{
SomethingEnabled = false;
DoSomething();
}));
}
}