C#6 Update
In C#6 ?. is now a language feature:
// C#1-5 propertyValue1 = myObject != null ? myObject.StringProperty : null; // C#6 propertyValue1 = myObject?.StringProperty;
The question below still applies to older versions, but if developing a new application using the new ?. operator is far better practice.
Original Question:
I regularly want to access properties on possibly null objects:
string propertyValue1 = null; if( myObject1 != null ) propertyValue1 = myObject1.StringProperty; int propertyValue2 = 0; if( myObject2 != null ) propertyValue2 = myObject2.IntProperty;
And so on…
I use this so often that I have a snippet for it.
You can shorten this to some extent with an inline if:
propertyValue1 = myObject != null ? myObject.StringProperty : null;
However this is a little clunky, especially if setting lots of properties or if more than one level can be null, for instance:
propertyValue1 = myObject != null ? (myObject.ObjectProp != null ? myObject.ObjectProp.StringProperty) : null : null;
What I really want is ?? style syntax, which works great for directly null types:
int? i = SomeFunctionWhichMightReturnNull(); propertyValue2 = i ?? 0;
So I came up with the following:
public static TResult IfNotNull<T, TResult>( this T input, Func<T, TResult> action, TResult valueIfNull ) where T : class { if ( input != null ) return action( input ); else return valueIfNull; } //lets us have a null default if the type is nullable public static TResult IfNotNull<T, TResult>( this T input, Func<T, TResult> action ) where T : class where TResult : class { return input.IfNotNull( action, null ); }
This lets me us this syntax:
propertyValue1 = myObject1.IfNotNull( x => x.StringProperty ); propertyValue2 = myObject2.IfNotNull( x => x.IntProperty, 0); //or one with multiple levels propertyValue1 = myObject.IfNotNull( o => o.ObjectProp.IfNotNull( p => p.StringProperty ) );
This simplifies these calls, but I’m not sure about checking this sort of extension method in – it does make the code a little easier to read, but at the cost of extending object. This would appear on everything, although I could put it in a specifically referenced namespace.
This example is a rather simple one, a slightly more complex one would be comparing two nullable object properties:
if( ( obj1 == null && obj2 == null ) || ( obj1 != null && obj2 != null && obj1.Property == obj2.Property ) ) ... //becomes if( obj1.NullCompare( obj2, (x,y) => x.Property == y.Property ) ...
What are the pitfalls of using extensions in this way? Are other coders likely to be confused? Is this just abuse of extensions?
I guess what I really want here is a compiler/language extension:
propertyValue1 = myObject != null ? myObject.StringProperty : null; //becomes propertyValue1 = myObject?StringProperty;
This would make the complex case far easier:
propertyValue1 = myObject != null ? (myObject.ObjectProp != null ? myObject.ObjectProp.StringProperty) : null //becomes propertyValue1 = myObject?ObjectProp?StringProperty;
This would only work for value types, but you could return nullable equivalents:
int? propertyValue2 = myObject?ObjectProp?IntProperty; //or int propertyValue3 = myObject?ObjectProp?IntProperty ?? 0;
We independently came up with the exact same extension method name and implementation: Null-propagating extension method. So we don’t think it’s confusing or an abuse of extension methods.
I would write your ‘multiple levels’ example with chaining as follows:
There’s a now-closed bug on Microsoft Connect that proposed ‘?.’ as a new C# operator that would perform this null propagation. Mads Torgersen (from the C# language team) briefly explained why they won’t implement it.