Method call if not null in C#
Solution 1:
From C# 6 onwards, you can just use:
MyEvent?.Invoke();
or:
obj?.SomeMethod();
The ?.
is the null-propagating operator, and will cause the .Invoke()
to be short-circuited when the operand is null
. The operand is only accessed once, so there is no risk of the "value changes between check and invoke" problem.
===
Prior to C# 6, no: there is no null-safe magic, with one exception; extension methods - for example:
public static void SafeInvoke(this Action action) {
if(action != null) action();
}
now this is valid:
Action act = null;
act.SafeInvoke(); // does nothing
act = delegate {Console.WriteLine("hi");}
act.SafeInvoke(); // writes "hi"
In the case of events, this has the advantage of also removing the race-condition, i.e. you don't need a temporary variable. So normally you'd need:
var handler = SomeEvent;
if(handler != null) handler(this, EventArgs.Empty);
but with:
public static void SafeInvoke(this EventHandler handler, object sender) {
if(handler != null) handler(sender, EventArgs.Empty);
}
we can use simply:
SomeEvent.SafeInvoke(this); // no race condition, no null risk
Solution 2:
What you're looking for is the Null-Conditional (not "coalescing") operator: ?.
. It's available as of C# 6.
Your example would be obj?.SomeMethod();
. If obj is null, nothing happens. When the method has arguments, e.g. obj?.SomeMethod(new Foo(), GetBar());
the arguments are not evaluated if obj
is null, which matters if evaluating the arguments would have side effects.
And chaining is possible: myObject?.Items?[0]?.DoSomething()
Solution 3:
A quick extension method:
public static void IfNotNull<T>(this T obj, Action<T> action, Action actionIfNull = null) where T : class {
if(obj != null) {
action(obj);
} else if ( actionIfNull != null ) {
actionIfNull();
}
}
example:
string str = null;
str.IfNotNull(s => Console.Write(s.Length));
str.IfNotNull(s => Console.Write(s.Length), () => Console.Write("null"));
or alternatively:
public static TR IfNotNull<T, TR>(this T obj, Func<T, TR> func, Func<TR> ifNull = null) where T : class {
return obj != null ? func(obj) : (ifNull != null ? ifNull() : default(TR));
}
example:
string str = null;
Console.Write(str.IfNotNull(s => s.Length.ToString());
Console.Write(str.IfNotNull(s => s.Length.ToString(), () => "null"));
Solution 4:
Events can be initialized with an empty default delegate which is never removed:
public event EventHandler MyEvent = delegate { };
No null-checking necessary.
[Update, thanks to Bevan for pointing this out]
Be aware of the possible performance impact, though. A quick micro benchmark I did indicates that handling an event with no subscribers is 2-3 times slower when using the the "default delegate" pattern. (On my dual core 2.5GHz laptop that means 279ms : 785ms for raising 50 million not-subscribed events.). For application hot spots, that might be an issue to consider.
Solution 5:
Yes, in C# 6.0 -- https://msdn.microsoft.com/en-us/magazine/dn802602.aspx.
object?.SomeMethod()