Click here to Skip to main content
Click here to Skip to main content

The Null Coalescing Operator (??)

By , 28 Sep 2007
 

Introduction

I'm constantly surprised by the number of developers who aren't aware of this handy piece of syntax. It's my favourite thing to come out of C# 2.0 and no developer should be without it.

Like the conditional (?:) operator's big brother... introducing it for your coding pleasure...

The Null Coalescing Operator (??)

The null-coalescing-operator is a brilliant new terse operator that provides syntax for beautifully concise if statements. Essentially, it returns the left-hand-side of the ?? operator, unless null, in which case it executes and returns the right-hand-side of the operator. This may be a statement or a variable reference. Let's jump straight to some examples:

// used inline outputs the value foo or if null returns Undefined
Console.WriteLine("The value of foo is " + (foo ?? "Undefined") + ".");
    
Input:  foo = "24";
Output: The value of foo is 24.
    
Input:  foo = null;
Output: The value of foo is Undefined.

The operator is right-associative meaning statements can be chained together; thus returning the first non-null instance:

// assigns foo to the first non-null instance, else returns Undefined
string foo = foo1 ?? foo2 ?? foo3 ?? foo4 ?? "Undefined";
    
Console.WriteLine("The value of foo is " + foo + ".");

Input:  foo1 = null;
        foo2 = null;
        foo3 = null;
        foo4 = null;
Output: The value of foo is Undefined.
    
Input:  foo1 = null;
        foo2 = "foo2";
        foo3 = null;
        foo4 = "foo4";
Output: The value of foo is foo2.

Handling null ViewState references:

// try to assign ViewState value as an int, else if null assign 123
int foo = (int?)ViewState["foo"] ?? 123;
    
Response.Write("The value of foo is " + foo + ".");
    
Input:  ViewState["foo"]=1;
Output:  The value of foo is 1.  
    
Input:  ViewState["foo"]=null;
Output:  The value of foo is 123.  

And my personal favorite, on demand field instantiation:

private IList<string> foo;

public IList<string> Foo
{
    get
    {
        return foo ?? (foo = new List<string>());
    }
}

Here's an interesting example derived from an idea in the discussions below. It shows how an operator override can be used within an object's definition to enable shorthand syntax for double-null checking. The scenario is checking an object property for null using a null-coalescing-operator, but also defaulting when null-object-reference occurs; which would normally cause a runtime exception. (Note that I don't recommend actually using this approach, I just thought it made an interesting example.)

public class Address
{
    private static Address Empty = new Address();
    public string StreetName = null;
    
    public static Address operator +(Address address)
    {
        return address ?? Empty
    }
}
  
Console.WriteLine("The street name is "+ (+address).StreetName ?? "n/a" + ".");
  
Input:  address = new Address();
Output:  The street name is n/a.  
    
Input:  address = new Address();
            address.StreetName = "Regent St";
Output:  The street name is Regent St.    
    
Input:  address = null;
Output:  The street name is n/a.

The Rules

To use the null-coalescing-operator, there are some compile-time ground rules.

  • The left-hand-side must evaluate to a reference or nullable type.
  • All evaluated statements must be of matching type, unless they can be implicitly converted.

Summary

As you can see from the examples above, this little gem is very powerful and the possibilities are endless. Of course the benefits are purely syntactical, but it helps keep the code clean and easier to follow. I hope you enjoy it as much as I do.

History

  • 28th September, 2007: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

TheCodeKing
Architect
United Kingdom United Kingdom
Member
Mike Carlisle - Technical Architect with over 10 years experience in a wide range of technologies.
 
@TheCodeKing

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralRe: A handy operatormemberDaniel Grunwald29 Sep '07 - 0:18 
Yes, '?.' looks better than '.?'. Though '?.' would be a single operator, as just 'address?' makes no sense. So 'address? ?? "n/a"' would be invalid syntax.
In my program there a few places where I need use "a?.b?.c?.d" - such nested accesses get horribly messy without the ?. operator, so I had to use the null object pattern. But I think patterns are just workarounds for missing language features.
 

GeneralRe: A handy operatormemberTheCodeKing28 Sep '07 - 13:09 
It's a winner for me, also prefer ?. as opposed to .?. Would be nice to use in conventional if statements as well to save writting the extra check.
 
if (address?.StreetName==null)
{
// do this if address is null or address.StreetName is null
}
else
{
// do that
}
 

GeneralRe: A handy operator [modified]memberTheCodeKing28 Sep '07 - 13:24 
Just playing with implicit operators. Obviously not as good as a framework implementation, but you could almost pull it off. Unfortunately it doesn't look possible to add a new ? operator, so had to use + instead.
 
 public class Address
 {
    public string StreetName = null;
 
    public static bool operator +(Address address)
    {
       return address != null;
    }
  }
 
  string street = (+a)?a.StreetName:"n/a"; 

... or another interesting play on operators...
 
 public class Address
 {
    private static Address Empty = new Address();
    public string StreetName = null;
 
    public static Address operator +(Address address)
    {
       return address ?? Empty
    }
  }
 
  string street = (+a).StreetName ?? "n/a";
 
-- modified at 19:48 Friday 28th September, 2007
 

GeneralRe: A handy operatormemberTheCodeKing28 Sep '07 - 12:42 
I guess you could say
 
string street = address==null ? new Address().StreetName : address.StreetName ?? "n/a";
 
but whether thats's helpful for others is debatable Smile | :)
 

GeneralRe: A handy operatormemberTheCodeKing28 Sep '07 - 12:44 
or hows about...
 
string street = (address ?? new Address()).StreetName ?? "n/a";
 

GeneralRe: A handy operatormemberlogan133728 Sep '07 - 12:56 
Yeah I considered that too. Hardly ideal tho as it involves creating a new object which could potentially involve a lot of overhead. Not to mention it only works if the object has a default constructor AND initializes the fields to null.
GeneralRe: A handy operatormemberTheCodeKing28 Sep '07 - 13:02 
Yes, I think Daniel had the best idea with the feature request
 
string street = address?.StreetName ?? "n/a";
 

GeneralRe: A handy operatormemberJoshuaMcKinney6 Oct '07 - 20:39 
Why not use the null object pattern?, i.e. if something can be empty meaningfully, indicate this in code
public class Street
{
    public static readonly Street Empty = new Street("n/a");
 
    private string value;
    public Street(string value)
    {
        this.value = value;
    }
 
    public override string ToString()
    {
        return value;
    }
}
 
public class Address
{
    public static readonly Address Empty = new Address(Street.Empty);
 
    private Street street = Street.Empty;
    public Street Street
    {
        get { return street; }
    }
	
    public Address(Street street)
    {
        this.street = street;
    }
}
Then you could instead of use:
Address address = null;
Console.WriteLine((address ?? Address.Empty).Street);
or even better never set the address to a meaningless null value:
Address address = Address.Empty;
Console.WriteLine(address.Street);
This also allows the ability to capture with more detail several unknown conditions.
E.g.
1. The user has not yet specified the address
2. The user has no fixed address
3. The user does not know the address
...
 
For each of these it would be reasonable to replace Street.Empty with another static readonly field (Street.NotSpecified, Street.Unknown, Street.NoFixedAddress, ...). We can then use the Street.ToString() directly or easily compare to those static fields if there is specific logic needed in the application.
our code becomes even more descriptive now:
Address address = Address.NotSpecified
 
I don't like the op + on address in the article. Syntactically great - you save a bunch of characters; however, semantically the positive of an address doesn't mean anything and only adds to a maintenance programmer's pain in having to deal with your app.
GeneralRe: A handy operatormemberlogan13378 Oct '07 - 7:42 
Yes I like the idea of providing more information representing the state of an object instead of just "null" which could mean several things, as you've illustrated. I think what we were really getting at here is that it would be convenient to have a syntactic means of checking whether or not a particular object was "not null", or in other words if it had a proper value.
 
I also don't like using symbols like + arbitrarily to represent operations, however this is also partly the fault of Microsoft for not allowing much flexibility when it comes to operator overloading in C#. It would really be nice if we could define our own symbols and combinations of symbols to mean certain syntactic things--then we could define the '?.' operator ourselves, for instance.
 
Unfortunately, we currently have to rely on MS to do this for us.
GeneralRe: A handy operatormemberTheCodeKing8 Oct '07 - 8:17 
That's right, I wasn't suggesting anyone use the (+) implementation from the example. I was seeing how close I could get to the imaginary null checking .? synatax we discussed in the thread eariler by messing with operators.

The JoshuaMcKinney example is much more the sort of code you might use in the real world, depending of course on the desired behaviour of the app.

 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 28 Sep 2007
Article Copyright 2007 by TheCodeKing
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid