107

null coalescing translates roughly to return x, unless it is null, in which case return y

I often need return null if x is null, otherwise return x.y

I can use return x == null ? null : x.y;

Not bad, but that null in the middle always bothers me -- it seems superfluous. I'd prefer something like return x :: x.y;, where what follows the :: is evaluated only if what precedes it is not null.

I see this as almost an opposite to null coalescence, kind of mixed in with a terse, inline null-check, but I'm [almost] certain that there is no such operator in C#.

Are there other languages that have such an operator? If so, what is it called?

(I know that I can write a method for it in C#; I use return NullOrValue.of(x, () => x.y);, but if you have anything better, I'd like to see that too.)

Community
  • 1
  • 1
Jay
  • 56,361
  • 10
  • 99
  • 123
  • Some have asked for something like x?.y in C#, but nothing like that exists. – Anthony Pegram May 28 '10 at 14:27
  • 1
    @Anthony Oh, that would be beautiful. Thanks. – Jay May 28 '10 at 14:30
  • 2
    In c++, that would easy enough to express as `return x ? x.y : NULL`. Yay for converting pointer types to booleans! – Phil Miller May 28 '10 at 15:42
  • 1
    @Novelocrat that is one of the things that irritates me most in C# is that they didn't follow the C if that if(anything) = true except when it's if(0, false, null) – Chris Marisic May 28 '10 at 16:37
  • 2
    @Chris: that's not an accurate statement about C. If you have a non-scalar variable (such as a struct), you can't use that in a condition. – Phil Miller May 28 '10 at 18:54
  • If it were implemented, I think a good syntax would be `x ?=> y`: return null if x is null, otherwise return y – Andy Feb 19 '14 at 00:21
  • Feature suggestions: `return x == null ? null : Whatever(x);`: http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/6170791-create-an-anti-null-coalescing-operator `return x == null ? null : x.Property;`: http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/3990187-add-operator-to-c – JohnLBevan Jul 14 '14 at 11:36

12 Answers12

68

There's the null-safe dereferencing operator (?.) in Groovy... I think that's what you're after.

(It's also called the safe navigation operator.)

For example:

homePostcode = person?.homeAddress?.postcode

This will give null if person, person.homeAddress or person.homeAddress.postcode is null.

(This is now available in C# 6.0 but not in earlier versions)

Stephen
  • 1,737
  • 2
  • 26
  • 37
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    Groovy also has the "Elvis operator", which allows default values other than `null`, e.g.: `def bar = foo ?: ""` – Craig Stuntz May 28 '10 at 14:33
  • 29
    I nominate this feature for C# 5.0. I don't know or care what Groovy actually is, but this is intuitive enough to use in any language. – György Andrasek May 28 '10 at 15:36
  • It is however being added to C# 6 now, hooray. – Jeff Mercado Jun 29 '15 at 20:24
  • 2
    Safe-navigation works for the trivial example posted, but you still need to use the ternary operator if you intend to use the non-null value in a function call, for example: `Decimal? post = pre == null ? null : SomeMethod( pre );`. It would be nice if I could reduce it down to "Decimal? post = pre :: SomeMethod( pre );" – Dai Jul 28 '16 at 11:07
  • @Dai: Given the number of permutations you might want of that, I'm happy enough with what we've got. – Jon Skeet Jul 28 '16 at 11:09
38

UPDATE: The requested feature was added to C# 6.0. The original answer from 2010 below should be considered of historical interest only.


We considered adding ?. to C# 4. It didn't make the cut; it's a "nice to have" feature, not a "gotta have" feature. We'll consider it again for hypothetical future versions of the language, but I wouldn't hold my breath waiting if I were you. It's not likely to get any more crucial as time goes on. :-)

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • Does ease of implementing a feature play into the decision to add it? I ask this because implementing that operator seems like a fairly straight forward, simple addition to the language. I'm no expert (just a recent grad with big love for C#), so please correct me! – Nick Strupat Oct 24 '11 at 22:38
  • 15
    @nick: Sure, implementing the lexer and parser is five minutes work. Then you start worrying about stuff like "does the IntelliSense engine handle it well?" and "how does the error-recovery system deal with it when you've typed the ? but not the . yet?" and just how many different things does "." mean in C# anyway, and how many of them deserve to have a ? before it, and what should the error messages be if you get it wrong, and how much testing is this feature going to need (hint: a lot.) And how are we going to document it and communicate the change, and... – Eric Lippert Oct 25 '11 at 06:01
  • 4
    @nick: To answer your question -- yes, the implementation cost is a factor, but a small one. There are no cheap features at the level we work at, only more or less expensive features. Five dollars worth of dev work to make the parser work in the correct-code case can easily turn into tens of thousands of dollars worth of design, implementation, testing, documentation and education. – Eric Lippert Oct 25 '11 at 06:03
  • 12
    @EricLippert I think this would be one of MAJOR "nice to have's", which have made C# so successful and also would perfectly serve a mission of making code as concise and expressive as possible! – Konstantin Oct 25 '11 at 10:42
  • I would like to see this added, what I REALLY want is the elvis operator: http://stackoverflow.com/questions/2929836/is-there-an-opposite-to-the-null-coalescing-operator-in-any-language#comment2983361_2929850 – Chris Marisic Jun 06 '12 at 12:33
  • 1
    @EricLippert What's the feature in C# 6.0 that would allow an inverse of ?? – sw1337 Oct 08 '21 at 20:27
  • @EricLippert I realize this question is old, but nullables are everywhere in our code base. It's like async-await in that regard; it tends to spread. I find myself doing `x is not null ? do() : null` all the time. Would be amazing to get `x ?. do()`. – Alexander Høst Jan 06 '22 at 16:49
  • 2
    @AlexanderHøst: I have not been on the C# team for almost ten years now, so telling me about your feature requests is unlikely to get any results :) The C# design process is open-sourced; feel free to post a suggestion on their github site if you have a language feature request. – Eric Lippert Jan 10 '22 at 23:38
18

If you've got a special kind of short-circuit boolean logic, you can do this (javascript example):

return x && x.y;

If x is null, then it won't evaluate x.y.

Eric
  • 95,302
  • 53
  • 242
  • 374
7

It just felt right to add this as an answer.

I guess the reason why there is no such thing in C# is because, unlike the coalescing operator (which is only valid for reference types), the reverse operation could yield either a reference or value type (i.e. class x with member int y - therefore it would unfortunately be unusable in many situations.

I'm not saying, however, that I wouldn't like to see it!

A potential solution to that problem would for the operator to automatically lift a value type expression on the right-hand-side to a nullable. But then you have the issue that x.y where y is an int will actually return an int? which would be a pain.

Another, probably better, solution would be for the operator to return the default value (i.e. null or zero) for the type on the right hand side if the expression on the left is null. But then you have issues distinguishing scenarios where a zero/null was actually read from x.y or whether it was supplied by the safe-access operator.

Andras Zoltan
  • 41,961
  • 13
  • 104
  • 160
  • when I first read the OP's question, this exact issue popped into my head, but I couldn't nail down how to articulate it. It's a very serious problem. +1 – rmeador May 28 '10 at 14:57
  • it's not a serious problem. Just use `int?` as the default return value, and the user can change it to an int if he wants. For example if I would like to call some method `Lookup` with a default value of -1 in case one of my references is `null`: `foo?.Bar?.Lookup(baz) ?? -1` – Qwertie Jun 07 '12 at 19:11
  • How about having `?. :` be a ternary operator, where the right-hand side is required to be of the same type as the appropriate member given in the middle? – supercat Jun 19 '13 at 16:17
6

Delphi has the : (rather than .) operator, which is null-safe.

They were thinking about adding a ?. operator to C# 4.0 to do the same, but that got the chopping block.

In the meantime, there's IfNotNull() which sort of scratches that itch. It's certainly larger than ?. or :, but it does let you compose a chain of operations that won't hork a NullReferenceException at you if one of the members is null.

Community
  • 1
  • 1
48klocs
  • 6,073
  • 3
  • 27
  • 34
3

In Haskell, you can use the >> operator:

  • Nothing >> Nothing is Nothing
  • Nothing >> Just 1 is Nothing
  • Just 2 >> Nothing is Nothing
  • Just 2 >> Just 1 is Just 1
dave4420
  • 46,404
  • 6
  • 118
  • 152
3

Haskell has fmap, which in this case I think is equivalent toData.Maybe.map. Haskell is purely functional, so what you are looking for would be

fmap select_y x

If x is Nothing, this returns Nothing. If x is Just object, this returns Just (select_y object). Not as pretty as dot notation, but given that it's a functional language, styles are different.

Norman Ramsey
  • 198,648
  • 61
  • 360
  • 533
2
public class ok<T> {
    T s;
    public static implicit operator ok<T>(T s) { return new ok<T> { s = s }; }
    public static implicit operator T(ok<T> _) { return _.s; }

    public static bool operator true(ok<T> _) { return _.s != null; }
    public static bool operator false(ok<T> _) { return _.s == null; }
    public static ok<T> operator &(ok<T> x, ok<T> y) { return y; }
}

I often need this logic for strings:

using ok = ok<string>;

...

string bob = null;
string joe = "joe";

string name = (ok)bob && bob.ToUpper();   // name == null, no error thrown
string boss = (ok)joe && joe.ToUpper();   // boss == "JOE"
J Bryan Price
  • 1,364
  • 12
  • 17
2

PowerShell let's you reference properties (but not call methods) on a null reference and it will return null if the instance is null. You can do this at any depth. I had hoped that C# 4's dynamic feature would support this but it does not.

$x = $null
$result = $x.y  # $result is null

$x = New-Object PSObject
$x | Add-Member NoteProperty y 'test'
$result = $x.y  # $result is 'test'

It's not pretty but you could add an extension method that will function the way you describe.

public static TResult SafeGet<T, TResult>(this T obj, Func<T, TResult> selector) {
    if (obj == null) { return default(TResult); }
    else { return selector(obj); }
}

var myClass = new MyClass();
var result = myClass.SafeGet(x=>x.SomeProp);
Josh
  • 68,005
  • 14
  • 144
  • 156
1

This is being added in C# vNext (Roslyn powered C#, releases with Visual Studio 2014).

It is called Null propagation and is listed here as complete. https://roslyn.codeplex.com/wikipage?title=Language%20Feature%20Status

It is also listed here as complete: https://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/3990187-add-operator-to-c

Micah Zoltu
  • 6,764
  • 5
  • 44
  • 72
1

Create a static instance of your class somewhere with all the right default values for the members.

For example:

z = new Thingy { y=null };

then instead of your

return x != null ? x.y : null;

you can write

return (x ?? z).y;
Terrance
  • 11,764
  • 4
  • 54
  • 80
Nick
  • 11
  • 1
  • I use that technique sometimes (e.g. (x ?? "").ToString()) but it's only practical on a few data types such as PODs and strings. – Qwertie Jun 07 '12 at 19:07
0

The so called "null-conditional operator" has been introduced in C# 6.0 and in Visual Basic 14.
In many situations it can be used as the exact opposite of the null-coalescing operator:

int? length = customers?.Length; // null if customers is null   
Customer first = customers?[0];  // null if customers is null  
int? count = customers?[0]?.Orders?.Count();  // null if customers, the first customer, or Orders is null

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators

Jpsy
  • 20,077
  • 7
  • 118
  • 115