Sunday, January 01, 2006
« Happy New Year 2006! | Main | New Microsoft MVP in ASP/ASP.NET 2006 »

Every so often something comes across one's desk that results in a “hey! what's that!?” moment.  Now I'd like to believe that I have acquired a deep level of comfort and familiarity with the syntax of my favorite development language (C#).  Today, however, I had one of those moments.  I saw a line of code that resembled:

Console.WriteLine(userName ?? "User name not specified");

Note the ?? operator.  It took me a bit to find information about it, I really had to do some digging - it wasn't coming up on the msdn sites...I wonder if the search engines just didn't like the question marks.  Whispering from the recesses of my mind I seemed to recall having seen it, but all memory of its usefulness had vanished...I had to relearn it.

Anyway, this operator (termed a null coalescing operator) is new in C# 2.0...and it's pretty slick.  The null coalescing operator provides inherent null-checking capabilities.  The result of the expression is based on whether the first operand is null.  If the first operand is not null, it is the result of the expression, otherwise, the result falls to the second operand.  In other words, return the first value if not null, otherwise the second.

In effect, the previous line could be written thus:

Console.WriteLine( null != userName ? userName : "User name not specified");

That's pretty awesome - especially since in general I'm a fan of the ternary, conditional operator (?:), I think I can really fall in love with this new capability.  I suppose the null coalescing operator (??) is just syntactic sugar, but I like it nonetheless.

Let's suppose you had a function named 'getCustomer' that accepts an id that is used to retrieve a customer object from some underlying store (such as a database, collection, file, etc).  If the customer exists, it is returned.  However, if it doesn't exist, a value of null is returned.  In this particular instance you might have an operation that indicates that if the customer doesn't exist to create a new one:

Customer cust = getCustomer(id);
if ( null == cust ) cust = new Customer();

You could effectively rewrite the previous lines as

Customer cust = getCustomer(id) ?? new Customer();

Note, you would NOT want to do the following for reasons which are self evident.

Customer cust = ( null == getCustomer(id) ) ? getCustomer(id) : new Customer();

A couple of links that I did eventually find which are good reads: Fritz Onion's blog and Oliver Sturm's blog.

Ya (re)learn something new everyday.

Sunday, January 01, 2006 8:40:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [44]  |  Trackback
Wednesday, January 04, 2006 5:30:00 AM (Mountain Standard Time, UTC-07:00)


Rock on. Thanks for posting this, I love the ?: operator and am always looking for good ways to reduce code clutter. I am certain I would have ran into this eventually, but better now than later.



Monday, January 09, 2006 4:26:00 AM (Mountain Standard Time, UTC-07:00)
- rated a 3.
Sorry, I'm just watching what happens when the rating control works right...
Monday, January 09, 2006 12:27:00 PM (Mountain Standard Time, UTC-07:00)
- rated a 5.
Awesome, I actually learned something from this blog
Thursday, February 23, 2006 9:02:00 PM (Mountain Standard Time, UTC-07:00)
It's very similar to SQL's ISNULL function, except that C# uses an infix operator and the SQL function is of course prefix.



Example: ISNULL(username,'User name not specified')
Steve
Monday, July 10, 2006 1:28:00 AM (Mountain Standard Time, UTC-07:00)
It's even cooler than that. The null coalescing operator does type forcing, too.



Imaging you have this:



public int? GetUserID() { ... }



int userID = GetUserID() ?? -1;



The ?? operator not only provides an alternative value if GetUserID returns null, but it also does type conversion, from the int? result of GetUserID to a non-nullable Int32, if it returns a non-null result.



Very cool :o)
Friday, November 03, 2006 11:02:00 PM (Mountain Standard Time, UTC-07:00)
Terrific. That's new for me. Thanks
Daniel
Friday, November 03, 2006 11:03:00 PM (Mountain Standard Time, UTC-07:00)
- rated a 5.
Interesting.
Daniel
Saturday, April 14, 2007 8:35:00 AM (Mountain Standard Time, UTC-07:00)
Thanks

When I read the title of your post I initially thought wow C# now has an equivalent coalesce to SQL.

Anyway this is great including the Owens comment !







Tuesday, May 08, 2007 3:14:00 AM (Mountain Standard Time, UTC-07:00)
Great job. Thanks for your help and posting.



Muhammad Khan
Tuesday, June 26, 2007 6:49:00 AM (Mountain Standard Time, UTC-07:00)
Yes cool. And thanks for the examples.
Thursday, July 05, 2007 8:34:00 AM (Mountain Standard Time, UTC-07:00)
- rated a 5.
awesome
sean
Friday, July 13, 2007 3:19:00 PM (Mountain Standard Time, UTC-07:00)
thanks...illustrated in a simple & understatdable manner...Keep it up!
Palani Saami
Tuesday, July 31, 2007 9:19:00 AM (Mountain Standard Time, UTC-07:00)
Thanks for the Information. This is a very userful operator.
Parminder Dhaliwal
Thursday, August 30, 2007 2:36:00 AM (Mountain Standard Time, UTC-07:00)
- rated a 5.
Great posting...this is so much easier than remebering the old syntax. Thanks!
Mark Orlando
Monday, September 10, 2007 12:50:00 AM (Mountain Standard Time, UTC-07:00)
I rank my code by how obvious it is.



If a MVP have to do digging to understand code, what about the people that are going to maintain your code? Do you require them to memorize special character combinations so they can be as "clever" as you are?



Replacing statements that reads in plain English with special character combinations is a very bad idea. A slippery slope to unreadable code.



Nothing is more obvious than if (null) x else y. It's English.
PMB
Wednesday, September 26, 2007 10:47:00 PM (Mountain Standard Time, UTC-07:00)
I totally agree with PMB. Why use such shortcuts when most may not know what it means. I find the if(null) x else y much more readable and easier to understand and i dont have to search the web for what it actually means which is what i will have to do when i forget it in two weeks.
Dom
Tuesday, October 02, 2007 3:14:00 PM (Mountain Standard Time, UTC-07:00)
I would expect those programming in C# to know all of it's operators and how they function. However, those operators that are slightly obscure (say a VB programmer would not understand them ;) can always be clarified by a comment (that's // for those not familiar). Anyway, that's not what this article was about....
RR
Tuesday, December 04, 2007 8:00:00 AM (Mountain Standard Time, UTC-07:00)
Here's the link to msdn site for explanation of all c# operators for your info:



http://msdn2.microsoft.com/en-us/library/6a71f45d(VS.80).aspx



Enjoy!!!
Dan
Monday, December 10, 2007 8:54:00 PM (Mountain Standard Time, UTC-07:00)
I can see this resulting in less readable code a lot of the time.



However, I can see it helping with the following common Idiom:



class A

{

private B _c;

private B CalculateCForA()

{

//expensive code...

}

//May be called zero or very many times.

//Value won't change for lifetime of A, or if it does

//we'll know about it and can update _c appropriately.

public B C

{

get

{

if(_c == null)

_c = CalculateCForA();

return _c;

}

}

}



With this operator the C property becomes:



public B C

{

get

{

return _c = _c ?? CalculateCForA();

}

}



Which while it is extremely terse, is quite idiomatic and could quickly become something where you'd see it and immediately grok what was intended.



Indeed I think the form a = x = x ?? y where x gets updated if it is null will definitely become common, it just makes so much sense.
Wednesday, December 19, 2007 10:35:00 PM (Mountain Standard Time, UTC-07:00)
thx
Friday, December 21, 2007 9:10:00 AM (Mountain Standard Time, UTC-07:00)
@PMB



I feel that its a necessary part of programming to learn more.



As far as read-ability of code,



x = MyObject.Parse(value) ?? new MyObject();



is as read-able to anyone worth their salt in the coding field as



message = string.Format("Hello {0}!", world);



Seriously, is it that bad to expect future programmers to read the specifications or at least have an inclination to understand the syntax of a language? It is not like we are flipping the meaning of TRUE and FALSE, it is just a new operator.



5 stars on the post amigo, well said.
Tomas Scheel
Wednesday, January 23, 2008 6:18:00 AM (Mountain Standard Time, UTC-07:00)
- rated a 5.
Can hardly believe I only just discovered this operator. 5 star post!!
Wednesday, January 23, 2008 11:37:00 AM (Mountain Standard Time, UTC-07:00)
I think it does not work with datareader.

i mean, can we use code like this:

string name = (dataReader["Name"] ?? " ");
saeed
Wednesday, January 23, 2008 7:40:00 PM (Mountain Standard Time, UTC-07:00)
I have learnt a lot.

it is too cool.



Gaurav Agrawal
Thursday, January 24, 2008 1:59:00 AM (Mountain Standard Time, UTC-07:00)
saeed,



Well, the NCO (Null Coalescing Operator) cannot be used in that sense because the valud returned by the DataReader isn't null. It's DBNull.Value, which is a singleton representation for a NULL value from the database. That's not the same this as a null reference in the .NET Framework. In that case, you still need to check for IsDBNull rather than use the NCO. Hope that helps.
Sunday, February 03, 2008 6:58:00 AM (Mountain Standard Time, UTC-07:00)
thanks for article, nice work
Wednesday, February 06, 2008 1:15:00 AM (Mountain Standard Time, UTC-07:00)
- rated a 5.
Nice illustration (esp compared to MSDN's attempt)
AB Leeds
Sunday, February 10, 2008 7:59:00 AM (Mountain Standard Time, UTC-07:00)
?? makes a lot of sense - anything to reduce the amount of tedium in my .NET coding day!
Wednesday, February 27, 2008 4:37:00 PM (Mountain Standard Time, UTC-07:00)
- rated a 5.
goooooooooood
anonymous
Wednesday, February 27, 2008 4:38:00 PM (Mountain Standard Time, UTC-07:00)
goooooooooood
anonymous
Thursday, March 06, 2008 1:24:00 PM (Mountain Standard Time, UTC-07:00)
Any way to leverage



arList.Add(new userObject(entryResult.Properties["displayName"].Value.ToString(),

entryResult.Properties["title"].Value.ToString(),

entryResult.Properties["mail"].Value.ToString()));





It pulls 3 attributes from users in a directory, and later gets displayed in a data grid. Unfortunately since title is not a required attribute, it is often null. It would be nice to be able to not throw an error on this each time, and just treat it as a blank.



Thanks!!
Bill
Friday, March 14, 2008 5:43:00 AM (Mountain Standard Time, UTC-07:00)
thanks for post
Friday, March 14, 2008 5:44:00 AM (Mountain Standard Time, UTC-07:00)
thanks for share, i will recommed my friends.
Friday, March 14, 2008 5:47:00 AM (Mountain Standard Time, UTC-07:00)
thanks, i will follow blog.L
Thursday, March 27, 2008 3:59:00 AM (Mountain Standard Time, UTC-07:00)
Thanks! nice article!
Monday, March 31, 2008 4:27:00 AM (Mountain Standard Time, UTC-07:00)
I'm confirm saeed this:



string name = (dataReader["Name"] ?? " ");
Thursday, April 03, 2008 5:01:00 AM (Mountain Standard Time, UTC-07:00)
Nice illustration, thanks
Tuesday, April 08, 2008 12:47:00 AM (Mountain Standard Time, UTC-07:00)
Thanks for the Information. This is a very userful operator.
Friday, April 18, 2008 3:00:00 AM (Mountain Standard Time, UTC-07:00)
This is equivalent to the Oracle's NVL function.
v.j.
Sunday, April 20, 2008 10:23:00 PM (Mountain Standard Time, UTC-07:00)
I think it does not work with datareader.

Thursday, April 24, 2008 8:33:00 PM (Mountain Standard Time, UTC-07:00)
Great posting ! This is so much easier than remebering the old syntax. Thanks !
Thursday, April 24, 2008 9:46:00 PM (Mountain Standard Time, UTC-07:00)
Great job.

Tahnks !
Thursday, April 24, 2008 10:32:00 PM (Mountain Standard Time, UTC-07:00)
nice share, thanks
Monday, May 19, 2008 4:10:00 AM (Mountain Standard Time, UTC-07:00)
this is so much easier than remebering the old syntax. Thanks!
Name
E-mail
Home page

Comment (Some html is allowed: a@href@title, b, i, strike) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

Enter the code shown (prevents robots):

Live Comment Preview