173

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)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Armstrongest
  • 15,181
  • 13
  • 67
  • 106

16 Answers16

227

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

string anybody = parm1 ?? localDefault ?? globalDefault;

vs.

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

It also works well if a 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"];
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
James Curran
  • 101,701
  • 37
  • 181
  • 258
  • 13
    The chaining is a big plus for the operator, removes a bunch of redundant IFs – chakrit Nov 10 '08 at 18:43
  • 1
    I just used it today to replace a simple IF block that I wrote before I knew about either ternary or null coalescing operator. The true and false branches of the original IF statement called the same method, replacing one of its arguments with a different value if a certain input is NULL. With the null coalescing operator, it's one call. This is really powerful when you have a method that needs two or more such substitutions! – David A. Gray Feb 28 '17 at 02:30
179

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
  • 9,260
  • 3
  • 35
  • 41
  • 9
    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 Nov 10 '08 at 18:29
  • 5
    This my primary usage of the Null Coalescing. – Chris Marisic Apr 27 '10 at 16:57
  • 8
    I might be missing something (I mostly use Java), but isn't there a race condition there? – Justin K Jun 29 '10 at 19:37
  • 10
    @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 Jun 29 '10 at 20:00
  • 5
    @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 Jun 29 '10 at 20:36
  • 7
    It doesn't have to be a Singleton to have a race condition. Just a shared instance of the class that contains LazyProp, and multiple threads that access LazyProp. Lazy is a better way to do this kind of thing, and is threadsafe by default (you can elect to modift the threadsafety of Lazy). – Niall Connaughton Jul 01 '13 at 07:40
53

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
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 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 Aug 10 '09 at 20:01
34

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
    +1. This is one big reason why I like the null coalescing operator. It's particularly useful when calling `MyMethod()` has any sort of side effects. – user Feb 15 '11 at 13:04
  • If `MyMethod()` does not have any effects outside of returning a value, the compiler knows not to call it twice, so you really don't have to worry about efficiency here in the majority of cases. – TinyTimZamboni Jan 15 '13 at 15:29
  • It is also keeps things more readable IMHO when `MyMethod()` is a chained sequence of dotted objects. Ex: `myObject.getThing().getSecondThing().getThirdThing()` – xdhmoore Mar 26 '13 at 20:20
  • @TinyTimZamboni, do you have a reference for this behavior of compiler? – Kuba Wyrostek Feb 16 '16 at 09:17
  • @KubaWyrostek I don't have knowledge of the specific workings of the C# compiler, but I have some experience with static compiler theory with llvm. There's a number of approaches a compiler can take to optimize a call like this. [Global Value Numbering](https://en.wikipedia.org/wiki/Global_value_numbering) will notice that the two calls to `MyMethod` are identical in this context, assuming that `MyMethod` is a Pure function. Another option is Automatic Memoization or just having the function close in cache. On the other hand: https://en.wikipedia.org/wiki/Global_value_numbering – TinyTimZamboni Feb 17 '16 at 18:24
  • MSDN on C# states that both condition and winning value are evaluated so I was wondering if C# specification follows this statement. To me this is not just a question of optimization. Two calls to `MyMethod()` are not thread-safe: returned value can differ between calls although the method has no side effects itself. – Kuba Wyrostek Feb 17 '16 at 19:22
24

Another thing to consider is that the coalesce operator doesn't call the get method of a property twice, as the ternary does.

So there are scenarios where you shouldn't use the ternary operator, for example:

public class A
{
    var count = 0;
    private int? _prop = null;
    public int? Prop
    {
        get 
        {
            ++count;
            return _prop
        }
        set
        {
            _prop = value;
        }
    }
}

If you use:

var a = new A();
var b = a.Prop == null ? 0 : a.Prop;

the getter will be called twice and the count variable will be equal to 2, and if you use:

var b = a.Prop ?? 0

the count variable will be equal to 1, as it should.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Fabio Lima
  • 386
  • 2
  • 7
  • 4
    This deserves more upvotes. I've read sooo many times that `??` is *equivalent* to `?:`. – Kuba Wyrostek Feb 16 '16 at 09:14
  • 1
    Valid point about a getter being called twice. But this example I would consider a bad design patter to have such misleadingly named getter to actually make changes to the object. – Linas Jun 29 '18 at 09:38
15

The biggest advantage that I find to the ?? operator is that you can easily convert nullable value types to non-nullable types:

int? test = null;
var result = test ?? 0; // 'result' is int, not int?

I frequently use this in LINQ queries:

Dictionary<int, int?> PurchaseQuantities;
// PurchaseQuantities populated via ASP .NET MVC form.
var totalPurchased = PurchaseQuantities.Sum(kvp => kvp.Value ?? 0);
// totalPurchased is int, not int?
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ryan
  • 2,948
  • 3
  • 30
  • 41
  • I may be a bit late here, but that second example will throw if `kvp == null`. And actually `Nullable` has a `GetValueOrDefault` method that I normally use. – CompuChip Nov 13 '13 at 13:29
  • 6
    KeyValuePair is a value type in the .NET framework, so accessing any of its properties would never throw a null reference exception. http://msdn.microsoft.com/en-us/library/5tbh8a42(v=vs.110).aspx – Ryan Nov 13 '13 at 14:51
9

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, and otherwise I get null. It works really well.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Matt Hamilton
  • 200,371
  • 61
  • 386
  • 320
7

You can use the null coalescing operator to make it a bit cleaner to handle the case where an optional parameter is not set:

public void Method(Arg arg = null)
{
    arg = arg ?? Arg.Default;
    ...
Niall Connaughton
  • 15,518
  • 10
  • 52
  • 48
6

I like to use the null coalesce operator to lazy load certain properties.

A very simple (and contrived) example just to illustrate my point:

public class StackOverflow
{
    private IEnumerable<string> _definitions;
    public IEnumerable<string> Definitions
    {
        get
        {
            return _definitions ?? (
                _definitions = new List<string>
                {
                    "definition 1",
                    "definition 2",
                    "definition 3"
                }
            );
        }
    } 
}
mlnyc
  • 2,636
  • 2
  • 24
  • 29
6

One thing I've been doing a lot lately is using null coalescing for backups to as. For example:

object boxed = 4;
int i = (boxed as int?) ?? 99;

Console.WriteLine(i); // Prints 4

It's also useful for backing up long chains of ?. that could each fail

int result = MyObj?.Prop?.Foo?.Val ?? 4;
string other = (MyObj?.Prop?.Foo?.Name as string)?.ToLower() ?? "not there";
Blue0500
  • 715
  • 8
  • 16
5

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

Actually, my experience is that all too few people are familiar with the ternary operator (or more correctly, the conditional operator; ?: is "ternary" in the same sense that || is binary or + is either unary or binary; it does however happen to be the only ternary operator in many languages), so at least in that limited sample, your statement fails right there.

Also, as mentioned before, there is one major situation when the null coalescing operator is very useful, and that is whenever the expression to be evaluated has any side effects at all. In that case, you cannot use the conditional operator without either (a) introducing a temporary variable, or (b) changing the actual logic of the application. (b) is clearly not appropriate in any circumstances, and while it's a personal preference, I don't like cluttering up the declaration scope with lots of extraneous, even if short-lived, variables, so (a) is out too in that particular scenario.

Of course, if you need to do multiple checks on the result, the conditional operator, or a set of if blocks, are probably the tool for the job. But for simple "if this is null, use that, otherwise use it", the null coalescing operator ?? is perfect.

user
  • 6,897
  • 8
  • 43
  • 79
  • Very late comment from me - but pleased to see somebody cover that a ternary operator is an operator with three arguments (of which there is now more than one in C#). – Steve Kidd Jul 26 '18 at 23:19
4

The 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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 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. – Armstrongest Mar 10 '09 at 18:30
  • Yeah, this is a frequent scenario... there is even a special method String.IsNullOrEmpty(string)... – Massimiliano Jun 17 '09 at 19:58
  • 12
    "the null-coalesce operator doesn't detect empty strings." Well it is the __null__ -coalescing operator, not the __nullOrEmpty__ -coalescing operator. And personally, I despise mixing null and empty values in languages that distinguish between the two, which makes interfacing with things that don't quite annoying. And I'm a bit obsessive-compulsive, so it annoys me when languages/implementations don't distinguish between the two anyway, even if I understand the reasoning why (like in [most implementations of?] SQL). – JAB Aug 05 '11 at 14:04
  • 3
    `??` can't be overloaded: http://msdn.microsoft.com/en-us/library/8edha89s(v=vs.100).aspx -- that would be a great one to have overloadable though. I use a combination: `s1.Nullify() ?? s2.Nullify()` where `string Nullify(this s)` returns a `null` in cases when the string is empty. – Kit Jul 16 '12 at 15:33
  • The only problem? I just found myself wanting ??= and found this thread while seeing if there was a way to do it. (Situation: The first pass loaded the exception cases, now I want to go back through and load default values into anything that didn't already get loaded.) – Loren Pechtel Oct 11 '13 at 01:05
3

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
  • 530,221
  • 131
  • 937
  • 1,214
3

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
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
HanClinto
  • 9,423
  • 3
  • 30
  • 31
2

It is a bit of a weird use case, but I had a method where an IDisposable object is potentially passed as an argument (and therefore disposed by the parent), but it could also be null (and so should be created and disposed in a local method)

To use it, the code either looked like

Channel channel;
Authentication authentication;

if (entities == null)
{
    using (entities = Entities.GetEntities())
    {
        channel = entities.GetChannelById(googleShoppingChannelCredential.ChannelId);
        [...]
    }
}
else
{
    channel = entities.GetChannelById(googleShoppingChannelCredential.ChannelId);
    [...]
}

But with a null coalesce it becomes much neater:

using (entities ?? Entities.GetEntities())
{
    channel = entities.GetChannelById(googleShoppingChannelCredential.ChannelId);
    [...]
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
PaulG
  • 13,871
  • 9
  • 56
  • 78
0

I have used it like this:

for (int i = 0; i < result.Count; i++)
{
    object[] atom = result[i];

    atom[3] = atom[3] ?? 0;
    atom[4] = atom[4] != null ? "Test" : string.Empty;
    atom[5] = atom[5] ?? "";
    atom[6] = atom[6] ?? "";
    atom[7] = atom[7] ?? "";
    atom[8] = atom[8] ?? "";
    atom[9] = atom[9] ?? "";
    atom[10] = atom[10] ?? "";
    atom[12] = atom[12] ?? false;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Muhammad Awais
  • 4,238
  • 1
  • 42
  • 37