141

Is it possible to somehow shorten this statement?

if (obj != null)
    obj.SomeMethod();

because I happen to write this a lot and it gets pretty annoying. The only thing I can think of is to implement Null Object pattern, but that's not what I can do every time and it's certainly not a solution to shorten syntax.

And similar problem with events, where

public event Func<string> MyEvent;

and then invoke

if (MyEvent != null)
    MyEvent.Invoke();
shA.t
  • 16,580
  • 5
  • 54
  • 111
Jakub Arnold
  • 85,596
  • 89
  • 230
  • 327
  • 48
    We considerred adding a new operator to C# 4: "obj.?SomeMethod()" would mean "call SomeMethod if obj is not null, otherwise, return null". Unfortunately it did not fit into our budget so we never implemented it. – Eric Lippert May 16 '09 at 15:42
  • 1
    @Eric : Is this comment still valid? I have seen somewhere that, it is available with 4.0 ? – CharithJ May 19 '11 at 02:45
  • @CharithJ: Nope. It was never implemented. – Eric Lippert May 19 '11 at 06:38
  • @Eric : "obj ?? SomeMethod()" is there which is cute. – CharithJ May 21 '11 at 13:47
  • "Value = myValue == null ? 0 : YourValue;" Can be written as "value = myValue ?? YourValue" – CharithJ May 21 '11 at 13:55
  • 4
    @CharithJ: I'm aware of the existance of the null coalescing operator. It doesn't do what Darth wants; he wants a lifted-to-nullable member access operator. (And by the way, your previous comment gives an incorrect characterization of the null coalescing operator. You meant to say "v = m == null ? y : m.Value can be written v = m ?? y".) – Eric Lippert May 22 '11 at 16:13
  • @EricLippert Why not something like `\`Method(...) ==> if (Method != null) Method(...) [else return null]`. By using a unary like operator that isn't used it should be quite easy to implement without creating major issues. One could have `?Method(...)` which would make a lot of sense but since `?` is already used in other places it could have unknown consequences. What would be nice with such a scheme is `?Method1(...) ?? Method2(...)` and one could chain calls... a sort of passthrough/cascading effect. Even more: `?Method1(...) ?? ?(() => { return ?Method2(...); })`. – Archival Oct 18 '12 at 06:21
  • 6
    For newer readers: C# 6.0 implements ?., so x?.y?.z?.ToString() will return null if x, y or z are null, or will return z.ToString() if none of them are null. – David Mar 09 '17 at 23:19

11 Answers11

215

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
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 2
    'm a little conflicted about this. In the case of an Action or event handler -- which is typically more independent -- this makes some sense. I wouldn't break encapsulation for a regular method, though. This implies creating the method in a separate, static class and I don't think losing encapsulation and degrading readability/code organization overall is worth the minor improvement in local readability – tvanfosson May 16 '09 at 12:35
  • 1
    @tvanfosson - indeed; but my point is that this is the only case I know of where it'll work. And the question itself raises the topic of delegates/events. – Marc Gravell May 16 '09 at 19:00
  • 1
    That code ends up generating a anonymous method somewhere, which really messes up the stack trace of any exception. Is it possible to give anonymous methods names? ;) – sisve May 17 '09 at 08:03
  • 1
    @MarcGravell isn't this called the null Conditional operator. – RayLoveless Nov 17 '17 at 17:37
  • What is the equivalent of ?. in VB.Net – mercu Jun 25 '18 at 16:34
  • 1
    @mercu it should be `?.` - in VB14 and above – Marc Gravell Jun 26 '18 at 10:27
32

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()

Pang
  • 9,564
  • 146
  • 81
  • 122
Vimes
  • 10,577
  • 17
  • 66
  • 86
  • 1
    This is fantastic. It's worth noting that this is a C# 6 feature... (Which would be implied from your VS2015 statement, but still worth noting). :) – Kyle Goode Jan 12 '16 at 23:51
10

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"));
katbyte
  • 2,665
  • 2
  • 28
  • 19
  • I had an [attempt to do it with extension methods](https://gist.github.com/omidkrad/57e386b7c3c983bbe5d1) and I ended up with pretty much the same code. However, the problem with this implementation is that it won't work with expressions that return a value type. So had to have a second method for that. – orad Jul 25 '14 at 00:21
5

Yes, in C# 6.0 -- https://msdn.microsoft.com/en-us/magazine/dn802602.aspx.

object?.SomeMethod()
epylar
  • 259
  • 2
  • 3
5

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.

Sven Künzler
  • 1,650
  • 1
  • 20
  • 22
  • 1
    So, you avoid a null-check by invoking an empty delegate ... a measurable sacrifice of both memory and time in order to save a few keystrokes? YMMV, but to me, a poor trade off. – Bevan May 17 '09 at 06:59
  • I've also seen benchmarks that show it's considerably more expensive to invoke an event with multiple delegates subscribed to it than with just one. – Greg D May 19 '11 at 12:52
3

This article by Ian Griffiths gives two different solutions to the problem that he concludes are neat tricks that you should not use.

Darrel Miller
  • 139,164
  • 32
  • 194
  • 243
  • 3
    And speaking as the author of that article, I'd add that you definitely shouldn't use it now that C# 6 solves this out of the box with the null conditional operators (?. and .[]). – Ian Griffiths Aug 10 '15 at 21:25
2

I agree with the answer by Kenny Eliasson. Go with Extension methods. Here is a brief overview of extension methods and your required IfNotNull method.

Extension Methods ( IfNotNull method )

Rohit
  • 6,365
  • 14
  • 59
  • 90
2

Cerating extention method like one suggested does not really solve issues with race conditions, but rather hide them.

public static void SafeInvoke(this EventHandler handler, object sender)
{
    if (handler != null) handler(sender, EventArgs.Empty);
}

As stated this code is the elegant equivalent to solution with temporary variable, but...

The problem with both that it's possible that subsciber of the event could be called AFTER it has unsubscribed from the event. This is possible because unsubscription can happen after delegate instance is copied to the temp variable (or passed as parameter in the method above), but before delegate is invoked.

In general the behaviour of the client code is unpredictable in such case: component state could not allow to handle event notification already. It's possible to write client code in the way to handle it, but it would put unnecesssary responsibility to the client.

The only known way to ensure thread safity is to use lock statement for the sender of the event. This ensures that all subscriptions\unsubscriptions\invocation are serialized.

To be more accurate lock should be applied to the same sync object used in add\remove event accessor methods which is be default 'this'.

andrey.tsykunov
  • 2,896
  • 2
  • 32
  • 21
  • This is not the race condition that is refered to. The race condition is if (MyEvent != null) //MyEvent is not null now MyEvent.Invoke(); //MyEvent is null now, bad things happen So with this race condition, I can not write a async event handler that is guarantied to work. However with your 'race condition', I can write a async event handler that is guarantied to work. Of course the calls to subscriber and unsubscriber need to be synchronous, or lock code is required there. – jyoung May 17 '09 at 13:05
  • Indeed. My analysis of this problem is posted here: http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx – Eric Lippert May 17 '09 at 15:05
1

Maybe not better but in my opinion more readable is to create an extension method

public static bool IsNull(this object obj) {
 return obj == null;
}
Kenny Eliasson
  • 2,047
  • 15
  • 23
  • 2
    what does the `return obj == null` mean. What will it return – TheTechGuy Jun 08 '12 at 18:12
  • 2
    It means that if `obj` is `null` the method will return `true`, I think. – Joel Mar 22 '13 at 12:05
  • 2
    How does this even answer the question? – Kugel Mar 04 '14 at 00:46
  • 1
    Late reply, but are you sure this would even work? Can you call an extension method on an object that is `null`? I'm pretty sure this doesn't work with the type's own methods, so I doubt it would work with extension methods either. I believe the best way to check if an object **is** `null` is `obj is null`. Unfortunately, to check if an object **is not** not `null` requires wrapping in parentheses, which is unfortunate. – natiiix Jun 24 '19 at 12:13
-1

I have made this generic extension that I use.

public static class ObjectExtensions {
    public static void With<T>(this T value, Action<T> todo) {
        if (value != null) todo(value);
    }
}

Then I use it like below.

string myString = null;
myString.With((value) => Console.WriteLine(value)); // writes nothing
myString = "my value";
myString.With((value) => Console.WriteLine(value)); // Writes `my value`
Trenskow
  • 3,783
  • 1
  • 29
  • 35
-5

There is a little-known null operator in C# for this, ??. May be helpful:

http://weblogs.asp.net/scottgu/archive/2007/09/20/the-new-c-null-coalescing-operator-and-using-it-with-linq.aspx

Matt Sherman
  • 8,298
  • 4
  • 37
  • 57