24

So I have been intrigued by the ?? operator, but have still been unable to use it. I usually think about it when I am doing something like:

var x = (someObject as someType).someMember;

If someObject is valid and someMember is null, I could do

var x = (someObject as someType).someMember ?? defaultValue;

but almost invariably I get into problems when someObject is null, and ?? doesn't help me make this any cleaner than doing the null check myself.

What uses have you guys found for ?? in practical situations?

captncraig
  • 22,118
  • 17
  • 108
  • 151

13 Answers13

32

The ?? operator is like the coalesce method in SQL, it gets you the first non-null value.

var result = value1 ?? value2 ?? value3 ?? value4 ?? defaultValue;
dance2die
  • 35,807
  • 39
  • 131
  • 194
Marcel Gosselin
  • 4,610
  • 2
  • 31
  • 54
  • 1
    Nice, never thought of using it this way! – TheSean Nov 06 '09 at 19:02
  • I can not think of a situation using ?? in this manner that a better design would not eliminate. A good use case would be interesting. – jphofmann Nov 06 '09 at 19:39
  • 2
    @jphofmann: One good use case from my current work. I have to search for a complex business object by calling a function. If the search fails null is returned by the search function. I have to repeatedly search with different search parameters until an object is found. The search rules are very easily understood from code like this: `var result = Find("A") ?? Find("Y") ?? Find("Q");` Using the `??` can make your code more compact and readable. – Martin Liversage Nov 07 '09 at 00:56
27

I agree with you that the ?? operator is usually of limited use-- it's useful to provide a fall-back value if something is null, but isn't useful to prevent a Null Reference Exception in cases when you want to continue drilling down into properties or methods of a sometimes-null reference.

IMHO, what's needed much more than ?? is a "null-dereference" operator which allows you to chain long property and/or method chains together, e.g. a.b().c.d().e without having to test each intermediate step for null-ness. The Groovy language has a Safe Navigation operator and it's very handy.

Luckily, it seems that the C# team is aware of this feature gap. See this connect.microsoft.com suggestion for the C# team to add a null-dereference operator to the C# language.

We get quite a number of requests for features similar to this one. The "?." version mentioned in the community discussion is closest to our hearts - it allows you to test for null at every "dot", and composes nicely with the existing ?? operator:

a?.b?.c ?? d

Meaning if any of a , a.b or a.b.c is null use d instead.

We are considering this for a future release, but it won't be in C# 4.0.

Thanks again,

Mads Torgersen, C# Language PM

If you also want this feature in C#, add your votes to the suggestion on the connect site! :-)

One workaround I use to get around the lack of this feature is an extension method like what's described in this blog post, to allow code like this:

string s = h.MetaData
            .NullSafe(meta => meta.GetExtendedName())
            .NullSafe(s => s.Trim().ToLower())

This code either returns h.MetaData.GetExtendedName().Trim().ToLower() or it returns null if h, h.MetaData, or h.MetaData.GetExtendedName() is null. I've also extended this to check for null or empty strings, or null or empty collections. Here's code I use to define these extension methods:

public static class NullSafeExtensions
{
    /// <summary>
    /// Tests for null objects without re-computing values or assigning temporary variables.  Similar to 
    /// Groovy's "safe-dereference" operator .? which returns null if the object is null, and de-references
    /// if the object is not null.
    /// </summary>
    /// <typeparam name="TResult">resulting type of the expression</typeparam>
    /// <typeparam name="TCheck">type of object to check for null</typeparam>
    /// <param name="check">value to check for null</param>
    /// <param name="valueIfNotNull">delegate to compute if check is not null</param>
    /// <returns>null if check is null, the delegate's results otherwise</returns>
    public static TResult NullSafe<TCheck, TResult>(this TCheck check, Func<TCheck, TResult> valueIfNotNull)
        where TResult : class
        where TCheck : class
    {
        return check == null ? null : valueIfNotNull(check);
    }

    /// <summary>
    /// Tests for null/empty strings without re-computing values or assigning temporary variables
    /// </summary>
    /// <typeparam name="TResult">resulting type of the expression</typeparam>
    /// <param name="check">value to check for null</param>
    /// <param name="valueIfNotNullOrEmpty">delegate to compute non-null value</param>
    /// <returns>null if check is null, the delegate's results otherwise</returns>
    public static TResult CheckNullOrEmpty<TResult>(this string check, Func<string, TResult> valueIfNotNullOrEmpty)
        where TResult : class
    {
        return string.IsNullOrEmpty(check) ? null : valueIfNotNullOrEmpty(check);
    }
    /// <summary>
    /// Tests for null/empty collections without re-computing values or assigning temporary variables
    /// </summary>
    /// <typeparam name="TResult">resulting type of the expression</typeparam>
    /// <typeparam name="TCheck">type of collection or array to check</typeparam>
    /// <param name="check">value to check for null</param>
    /// <param name="valueIfNotNullOrEmpty">delegate to compute non-null value</param>
    /// <returns>null if check is null, the delegate's results otherwise</returns>
    public static TResult CheckNullOrEmpty<TCheck, TResult>(this TCheck check, Func<TCheck, TResult> valueIfNotNullOrEmpty)
        where TCheck : ICollection
        where TResult : class
    {
        return (check == null || check.Count == 0) ? null : valueIfNotNullOrEmpty(check);
    }
}
Justin Grant
  • 44,807
  • 15
  • 124
  • 208
  • I like the idea of the helper method, but its sad that it has to be such a hack. – captncraig Nov 09 '09 at 17:06
  • Yep. If you want to get this into C#, there's an easy way to hurry the process along: go vote for the suggestion at https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=432830 ! :-) – Justin Grant Nov 09 '09 at 17:32
  • 404 on the "safe-null-dereferencing operator" link. And also on the microsoft connect link. – Jonathon Reinhart Sep 10 '12 at 15:02
  • @JonathonReinhart - thanks for reporting broken links, I just fixed them with updated URLs. Also, to vote for this feature to be added to C#, don't use the link in my comment above as it's broken too. Instead, go here: http://connect.microsoft.com/VisualStudio/feedback/details/432830 – Justin Grant Nov 20 '13 at 05:57
  • It looks like we may finally get this feature in c# 6. Yaay. – captncraig Feb 11 '14 at 18:17
22

I usually use it for strings or nullable types.

string s = someString ?? "Default message";

is easier than

   string s;
   if(someString == null)
     s = "Default Message";         
   else
     s = someString;

or

  string s = someString != null ? someString : "Default Message";
Ed S.
  • 122,712
  • 22
  • 185
  • 265
Brandon
  • 68,708
  • 30
  • 194
  • 223
  • 2
    Very true, but it isn't equivalent to your middle statement as if someString == string.Empty, the ?? operator won't fire. – Michael La Voie Nov 06 '09 at 18:53
  • 1
    @The Lame Duck, you're right. An empty string is not the same as a null string, this was just an example. Really I could just replace the string checks with null checks. Which I should do... – Brandon Nov 06 '09 at 18:54
  • 1
    See also string.IsNullOrEmpty(s). – TrueWill Nov 06 '09 at 19:05
  • @TrueWill, thats what I had before the edit, but as The Lame Duck pointed out, String.IsNUllOrEmpty is not the same as the null coalescing operator. And @Ed Swangren, thanks. when I made the edit I mixed up the cases. It's Friday, so I'm just a mess :P – Brandon Nov 06 '09 at 19:25
12

I often use it for lazily instantiated objects in properties, e.g.

public MyObject MyProperty
{
    get
    {
        return this.myField ?? (this.myField = new MyObject());
    }
}

This takes advantage of the fact that in C# an assignment is an expression so you can assign and use the result of the expression (the assigned value) all in the same statement. I still feel slightly dirty about this code pattern, but it is terser than the alternative (below) so it just about wins.

public MyObject MyProperty
{
    get
    {
        if (this.myField == null)
        {
            this.myField = new MyObject();
        }

        return this.myField;
    }
}
Greg Beech
  • 133,383
  • 43
  • 204
  • 250
8

Just as an FYI, the ternary operator generates a different sequence of IL from the null coalescing operator. The first looks something like such:

// string s = null;
// string y = s != null ? s : "Default";
    ldloc.0
    brtrue.s notnull1
    ldstr "Default"
    br.s isnull1
    notnull1: ldloc.0
    isnull1: stloc.1

And the latter looks like such:

// y = s ?? "Default";
    ldloc.0
    dup
    brtrue.s notnull2
    pop
    ldstr "Default"
    notnull2: stloc.1

Based on this, I'd say the null coalescing operator is optimized for its purpose and is not just syntactic sugar.

Jesse C. Slicer
  • 19,901
  • 3
  • 68
  • 87
7

?? is a null check operator, in effect.

The reason your code gets into trouble is that if "someObject is null, then .someMember is a property on a null object. You'll have to check someObject for null first.

EDIT:

I should add that yes, I do find ?? to be very useful, especially in handling database input, especially from LINQ, but also in other cases. I use it heavily.

Cylon Cat
  • 7,111
  • 2
  • 25
  • 33
3

I've been using it with App.Config stuff

string somethingsweet = ConfigurationManager.AppSettings["somesetting"] ?? "sugar";
kenny
  • 21,522
  • 8
  • 49
  • 87
2

The most useful is when dealing with nullable types.

bool? whatabool;
//...
bool realBool = whatabool ?? false;

without ?? you would need to write the following, which is much more confusing.

bool realbool = false;
if (whatabool.HasValue)
    realbool = whatabool.Value;

I find this operator very useful for nullable types, but other than that I don't find myself using it very much. Definitely a cool shortcut.

TheSean
  • 4,516
  • 7
  • 40
  • 50
1

In your case you can create DefaultObject as a static property and use like below ...

var x = (someObject as someType ?? someType.DefaultObject).someMember;

Where your DefaultObject will return a static, read-only object.

Like EventArgs.Empty, String.Empty etc...

Don Kirkby
  • 53,582
  • 27
  • 205
  • 286
Akash Kava
  • 39,066
  • 20
  • 121
  • 167
  • This seems like dangerous business to me. If I want a property of an object as long as it's not null, this code will result in situations where I don't even know if the object exists or not; maybe it just happens to share a property with the `DefaultObject`, or maybe it's null. – Dan Tao Nov 06 '09 at 19:10
  • @Dan, if you care whether the object exists or not, then check someObject == null. If you just want to display something readable to the user, then use SomeType.DefaultObject. FYI, this refactoring is called Introduce Null Object. – Don Kirkby Nov 06 '09 at 19:43
1

I use it in working with methods that can return null under normal operation.

for example, lets say that I have a container class that has a Get method that returns null if the container doesn't contain a key (or maybe null is a valid association). Then I might do something like this:

string GetStringRep(object key) {
    object o = container.Get(key) ?? "null";
    return o.ToString();
}

clearly, these two sequences are equivalent:

foo = bar != null ? bar : baz;
foo = bar ?? baz;

The second is merely more terse.

plinth
  • 48,267
  • 11
  • 78
  • 120
  • Actually, that's not 100% true. The ternary operator generates a different sequence of IL from the null coalescing operator. The first looks something like such: ldloc.0 brfalse.s isnull1 ldloc.0 br.s notnull1 isnull1: ldstr "Default" notnull1: stloc.1 And the latter looks like such: ldloc.0 dup brtrue.s notnull2 pop ldstr "Default" notnull2: stloc.1 Based on this, I'd say the null coalescing operator is optimized for its purpose and is not just pure syntactic sugar. – Jesse C. Slicer Nov 06 '09 at 20:54
  • And I sure apologize for the formatting snafu. Ugh. I'll post it as an answer to to look a little cleaner. – Jesse C. Slicer Nov 06 '09 at 20:54
1

It often seems to be a nice idea to replace a verbose bit of syntax with a more compact form. But usually it ends up just obfuscating the code without really gaining anything. Modern standards advocate longer and more descriptive variable names and use of more verbose layout styles in order to make code more readable & more maintainable.

If I'm going to train my brain to quickly parse ??, I need to find a situation where it shows a clear advantage - something that can't be done another way, or somewhere that it saves a significant amount of typing.

And this is where ?? falls down for me. It is useful so infrequently and ?: and if/else are such quick and readable alternatives that there really seems little point in using a different syntax that achieves nothing new.

a = b ?? c ?? d ?? e; sounds great. But I've never needed to do that!

What I find irritating is that I want to use ??, but every single time I think "ooh, maybe I can use ?? here", I realise that I don't want to use the object itself, but a member of it.

name = (user == null) ? "doe" : user.Surname;

And unfortunately, ?? doesn't help here.

Jason Williams
  • 56,972
  • 11
  • 108
  • 137
  • P.S. I don't develop web pages or LINQ database queries, though, so maybe ?? is just aimed at a different style of programming... – Jason Williams Nov 06 '09 at 19:35
0

I've had the exact same problem as you, but in the space of using LinqToXML a tag may not be in the document so using ?? isn't viable for coallescing the property on that tag.

Since there are no such thing as global variables in C# everything is in a class so I find, like you, that ?? is mostly useless.

Even a simple property getter like:

MyObject MyObj() { get { return _myObj ?? new MyObj(); } }

Is probably better served by an initializer...

I imagine that like in SQL it would be somewhat useful in Linq queries, but I can't really derive one at this moment.

Pickle
  • 181
  • 3
0

I use the null-coalescing operator often when parsing strings into other data types. I have a set of extension methods that wrap things like Int32.TryParse and return a nullable int instead of exposing an output parameter to the rest of my code. Then I can parse a string and provide a default value if the parse failed, in a single line of code.

// ToNullableInt(), is an extension method on string that returns null
// if the input is null and returns null if Int32.TryParse fails.

int startPage = Request.QueryString["start"].ToNullableInt() ?? 0;
Joel Mueller
  • 28,324
  • 9
  • 63
  • 88