views:

1571

answers:

10

I know the standard way of using the Null coalescing operator in C# is to set default values.

string nobody = null;
string somebody = "Bob Saget";
string anybody = "";

anybody = nobody   ?? "Mr. T"; // returns Mr. T
anybody = somebody ?? "Mr. T"; // returns "Bob Saget"

But what else can ?? be used for? It doesn't seem as useful as the ternary operator, apart from being more concise and easier to read than:

nobody = null;
anybody = nobody == null ? "Bob Saget" : nobody; // returns Bob Saget

So given that fewer even know about null coalescing operator...

Have you used ?? for something else?

Is ?? necessary, or should you just use the ternary operator (that most are familiar with)

+2  A: 

Is ?? necessary, or should you just use the ternary operator (that most are familiar with)

You should use what best expresses your intent. Since there is a null coalesce operator, use it.

On the other hand, since it's so specialized, I don't think it has other uses. I would have preferred an appropriate overload of the || operator, as other languages do. This would be more parsimonious in the language design. But well …

Konrad Rudolph
+23  A: 

Well, first of all, it's much easier to chain than the standard ternary:

string anybody = parm1 ?? localDefault ?? globalDefault;

vs.

string anyboby = (parm1 != null) ? parm1 
               : ((localDefault != null) ? localDefault 
               : globalDefault);

It also works well if null-possible object isn't a variable:

string anybody = Parameters["Name"] 
              ?? Settings["Name"] 
              ?? GlobalSetting["Name"];

vs.

string anybody = (Parameters["Name"] != null ? Parameters["Name"] 
                 : (Settings["Name"] != null) ? Settings["Name"]
                 :  GlobalSetting["Name"];
James Curran
The chaining is a big plus for the operator, removes a bunch of redundant IFs
chakrit
+31  A: 

I've used it as a lazy load one-liner:

public MyClass LazyProp
{
    get { return lazyField ?? (lazyField = new MyClass()); }
}

Readable? Decide for yourself.

Cristian Libardo
Hmmm, you found a counterexample to "why would someone want to use it as an obfuscated IF"... that is actually very readable to me.
Godeke
This my primary usage of the Null Coalescing.
Chris Marisic
I might be missing something (I mostly use Java), but isn't there a race condition there?
Justin K
@Justin K - There is only a race condition if multiple threads are accessing the LazyProp property of the same object. It's easily fixable with a lock, if thread safty of each instance is required. Clearly in this example, it is not required.
Jeffrey L Whitledge
@Jeffrey: If it were clear, I wouldn't have asked the question. :) When I saw that example, I immediately thought of a singleton member, and since I happen to do most of my coding in a multithreaded environment... But, yeah, if we assume the code is correct, anything extra is unnecessary.
Justin K
@Justin K - Singletons! Oooo, you used the S word! :-P
Jeffrey L Whitledge
+1  A: 

Cool! Count me as someone who didn't know about the null coalescing operator -- that's pretty nifty stuff.

I find it much easier to read than the ternary operator.

The first place that comes to mind where I might use it is to keep all of my default parameters in a single place.

public void someMethod( object parm2, ArrayList parm3 )
{ 
  someMethod( null, parm2, parm3 );
}
public void someMethod( string parm1, ArrayList parm3 )
{
  someMethod( parm1, null, parm3 );
}
public void someMethod( string parm1, object parm2, )
{
  someMethod( parm1, parm2, null );
}
public void someMethod( string parm1 )
{
  someMethod( parm1, null, null );
}
public void someMethod( object parm2 )
{
  someMethod( null, parm2, null );
}
public void someMethod( ArrayList parm3 )
{
  someMethod( null, null, parm3 );
}
public void someMethod( string parm1, object parm2, ArrayList parm3 )
{
  // Set your default parameters here rather than scattered through the above function overloads
  parm1 = parm1 ?? "Default User Name";
  parm2 = parm2 ?? GetCurrentUserObj();
  parm3 = parm3 ?? DefaultCustomerList;

  // Do the rest of the stuff here
}
HanClinto
You might as well learn about "constructor chaining"..
chakrit
+7  A: 

I've found it useful in two "slightly odd" ways:

  • As an alternative for having an out parameter when writing TryParse routines (i.e. return the null value if parsing fails)
  • As a "don't know" representation for comparisons

The latter needs a little bit more information. Typically when you create a comparison with multiple elements, you need to see whether the first part of the comparison (e.g. age) gives a definitive answer, then the next part (e.g. name) only if the first part didn't help. Using the null coalescing operator means you can write pretty simple comparisons (whether for ordering or equality). For example, using a couple of helper classes in MiscUtil:

public int Compare(Person p1, Person p2)
{
    return PartialComparer.Compare(p1.Age, p2.Age)
        ?? PartialComparer.Compare(p1.Name, p2.Name)
        ?? PartialComparer.Compare(p1.Salary, p2.Salary)
        ?? 0;
}

Admittedly I now have ProjectionComparer in MiscUtil, along with some extensions, which make this kind of thing even easier - but it's still neat.

The same can be done for checking for reference equality (or nullity) at the start of implementing Equals.

Jon Skeet
I like that. very innovative.
Atømix
I like what you did with the PartialComparer, but was looking for cases where I need to keep the evaluated expression variables. I am not versed in lambdas and extensions, so could you see if the following adheres to a similar pattern (i.e. does it work)? http://stackoverflow.com/questions/1234263/#1241780
maxwellb
+4  A: 

I've used ?? in my implementation of IDataErrorInfo:

public string Error
{
    get
    {
        return this["Name"] ?? this["Address"] ?? this["Phone"];
    }
}

public string this[string columnName]
{
    get { ... }
}

If any individual property is in an "error" state I get that error, otherwise I get null. Works really well.

Matt Hamilton
Interesting. You're using "this" as a property. I've never done that.
Atømix
Yeah, it's part of how IDataErrorInfo works. Generally that syntax is only useful on collection classes.
Matt Hamilton
<Voice kind="Borat">VERY NICE!
Robert Fraser
+1  A: 

Another advantage is that the ternary operator requires a double evaluation or a temporary variable.

Consider this, for instance:

string result = MyMethod() ?? "default value";

while with the ternary operator you are left with either:

string result = (MyMethod () != null ? MyMethod () : "default value");

which calls MyMethod twice, or:

string methodResult = MyMethod ();
string result = (methodResult != null ? methodResult : "default value");

Either way, the null coalescing operator is cleaner and, I guess, more efficient.

+1  A: 

Only problem is the null-coalesce operator doesn't detect empty strings.


i.e.

string result1 = string.empty ?? "dead code!";

string result2 = null ?? "coalesced!";

OUTPUT:

result1 = ""

result2 = coalesced!


I'm currently looking into overriding the ?? operator to work around this. It sure would be handy to have this built into the Framework.

Thoughts?

You can do this with Extension methods, but I agree, it would be a nice addition to the code and very useful in a web context.
Atømix
Yeah, this is a frequent scenario... there is even a special method String.IsNullOrEmpty(string)...
Yacoder
Same here. I wish it would work with empty strings...
Pawel Krakowiak
+1  A: 

Have a look at this link.. It show good use of Null-Coalescing Operator

http://aspdotnethacker.blogspot.com/2010/04/c-null-coalescing-operator.html

Experts Comment