views:

505

answers:

8

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

+20  A: 

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.

(And no, C# doesn't have at the moment.)

Jon Skeet
Groovy also has the "Elvis operator", which allows default values other than `null`, e.g.: `def bar = foo ?: "<null>"`
Craig Stuntz
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.
Jurily
+5  A: 

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.

48klocs
+9  A: 

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
+3  A: 

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
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
+1  A: 

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 Einstein
+1  A: 

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
Dave Hinton
+1  A: 

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
+5  A: 

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