conditional-operator ?. - why do we prefer ? to ?? operator in c#?




null coalescing (7)

I recently found that we can use ?? operator to check nulls. Please check the below code samples:

   var res = data ?? new data();

This is exactly similar to

   var res = (data==null) ? new data() : data ;

I checked my whole project source repository and some of other open source projects. And this ?? operator never been used.

I just wondering is there any reason behind this, like performance problems or something?

EDIT:

I just updated my sample code based on the comments from recursive & Anton. Its a mistake in careless. :(


Answers

I would have thought the equivalent of

var res = data ?? data.toString();

would be

var res = (data!=null) ? data : data.toString();

I think it's just a habit from other languages. AFAIK, ?? operator is not used in any other language.


The ?? operator (also known as the null-coalescing operator) is less known than the ternary operator, as it made its debut with .NET 2.0 and Nullable Types. Reasons for not using it probably include not begin aware that it exists, or being more familiar with the ternary operator.

That said, checking for null is not the only thing the ternary operator is good for, so it's not a replacement for it as such, more like a better alternative for a very specific need. :)


Based on Bob's answer

public object nullCoalesce(object a, object b, object c)
{
    return a ?? b ?? c;
}
public object ternary(object a, object b, object c)
{
    return a != null ? a : b != null ? b : c;
}
public object ifThenElse(object a, object b, object c)
{
    if (a != null)
        return a;
    else if (b != null)
        return b;
    else
        return c;
}

... this is the IL from release builds ...

.method public hidebysig instance object nullCoalesce(
    object a, 
    object b, 
    object c) cil managed
{
    .maxstack 8
    L_0000: ldarg.1 
    L_0001: dup 
    L_0002: brtrue.s L_000b
    L_0004: pop 
    L_0005: ldarg.2 
    L_0006: dup 
    L_0007: brtrue.s L_000b
    L_0009: pop 
    L_000a: ldarg.3 
    L_000b: ret 
}

.method public hidebysig instance object ternary(
    object a, 
    object b, 
    object c) cil managed
{
    .maxstack 8
    L_0000: ldarg.1 
    L_0001: brtrue.s L_000a
    L_0003: ldarg.2 
    L_0004: brtrue.s L_0008
    L_0006: ldarg.3 
    L_0007: ret 
    L_0008: ldarg.2 
    L_0009: ret 
    L_000a: ldarg.1 
    L_000b: ret 
}

.method public hidebysig instance object ifThenElse(
    object a, 
    object b, 
    object c) cil managed
{
    .maxstack 8
    L_0000: ldarg.1 
    L_0001: brfalse.s L_0005
    L_0003: ldarg.1 
    L_0004: ret 
    L_0005: ldarg.2 
    L_0006: brfalse.s L_000a
    L_0008: ldarg.2 
    L_0009: ret 
    L_000a: ldarg.3 
    L_000b: ret 
}

One reason (as others have already touched) is likely to be lack of awareness. It could also be (as in my own case), a wish to keep the number of approaches to do similar things in a code base down as much as possible. So I tend to use the ternary operator for all compact if-a-condition-is-met-do-this-otherwise-do-that situations.

For instance, I find the following two statements rather similar on a conceptual level:

return a == null ? string.Empty : a;    
return a > 0 ? a : 0;

One reason I can think of is that this operator was introduced in .NET 2.0 so the code for .NET 1.1 cannot have it.

I agree with you, we should be using this more often.

ref link


This, I got from one of Bill Gates' blog. I need to find it on my browser history and I'll give you the link.

The Javascript code to do the same thing (as requested):

function posted(t) {
    var now = new Date();
    var diff = parseInt((now.getTime() - Date.parse(t)) / 1000);
    if (diff < 60) { return 'less than a minute ago'; }
    else if (diff < 120) { return 'about a minute ago'; }
    else if (diff < (2700)) { return (parseInt(diff / 60)).toString() + ' minutes ago'; }
    else if (diff < (5400)) { return 'about an hour ago'; }
    else if (diff < (86400)) { return 'about ' + (parseInt(diff / 3600)).toString() + ' hours ago'; }
    else if (diff < (172800)) { return '1 day ago'; } 
    else {return (parseInt(diff / 86400)).toString() + ' days ago'; }
}

Basically, you work in terms of seconds...







c# conditional-operator