574

With C# 6.0 in the VS2015 preview we have a new operator, ?., which can be used like this:

public class A { string PropertyOfA { get; set; } } ... var a = new A(); var foo = "bar"; if(a?.PropertyOfA != foo) { //somecode } 

What exactly does it do?

2

3 Answers 3

790

It's the null conditional operator. It basically means:

"Evaluate the first operand; if that's null, stop, with a result of null. Otherwise, evaluate the second operand (as a member access of the first operand)."

In your example, the point is that if a is null, then a?.PropertyOfA will evaluate to null rather than throwing an exception - it will then compare that null reference with foo (using string's == overload), find they're not equal and execution will go into the body of the if statement.

In other words, it's like this:

string bar = (a == null ? null : a.PropertyOfA); if (bar != foo) { ... } 

... except that a is only evaluated once.

Note that this can change the type of the expression, too. For example, consider FileInfo.Length. That's a property of type long, but if you use it with the null conditional operator, you end up with an expression of type long?:

FileInfo fi = ...; // fi could be null long? length = fi?.Length; // If fi is null, length will be null 
Sign up to request clarification or add additional context in comments.

23 Comments

@SLaks: I thought it was "conditional null" but I could be wrong. Last time I checked the Roslyn language features docs, it hadn't been renamed to either. Maybe the source is the authority here - will check.
@SLaks: Sure. In SyntaxKind it's apparently ConditionalAccessExpression which is annoyingly neither of them...
i preferred the name "Elvis" operator :P
Just for the record I've seen five different names for this operator: safe navigation, null-conditional, null propagation, conditional access, Elvis.
Useful to note... you can also use the null conditional on arrays, like: a?[x]
|
150

It can be very useful when flattening a hierarchy and/or mapping objects. Instead of:

if (Model.Model2 == null || Model.Model2.Model3 == null || Model.Model2.Model3.Model4 == null || Model.Model2.Model3.Model4.Name == null) { mapped.Name = "N/A" } else { mapped.Name = Model.Model2.Model3.Model4.Name; } 

It can be written like (same logic as above)

mapped.Name = Model.Model2?.Model3?.Model4?.Name ?? "N/A"; 

DotNetFiddle.Net Working Example.

(the ?? or null-coalescing operator is different than the ? or null conditional operator).

It can also be used out side of assignment operators with Action. Instead of

Action<TValue> myAction = null; if (myAction != null) { myAction(TValue); } 

It can be simplified to:

myAction?.Invoke(TValue); 

DotNetFiddle Example:

using System;

public class Program { public static void Main() { Action<string> consoleWrite = null; consoleWrite?.Invoke("Test 1"); consoleWrite = (s) => Console.WriteLine(s); consoleWrite?.Invoke("Test 2"); } } 

Result:

Test 2

Basically, I have applied ?. operator after Model as well. I am trying to know that whether it can be applied directly to the model or does it only work with the navigation properties?

The ? or null conditional operator operators on the left value, regardless of the type of value. And the compiler doesn't care what the value is on the right. It's simple compiler magic (meaning it does something you can already do, just in a simplified why).

For example

 var a = model?.Value; 

is the same as saying

 var a = model == null ? null : model.Value; 

In the second case the evaluation of checking for null has no associate with the value returned. The null conditional operator basically just always return null if the left value is null.

The type of member (Method, Field, Property, Constructor) .Value is irrelevant.

The reason your DotNetFiddle example doesn't work is because the compiler being use for the .Net 4.7.2 isn't compatible with the c# version that support the null conditional operator. Changing it to .Net 5, works:

https://dotnetfiddle.net/7EWoO5

7 Comments

To save people looking up what the ?? is.. It is the null-coalescing operator and will return Name if it is not null, otherwise it will return "N/A".
@Erik Philips I think you need to add || Model.Model2.Model3.Model4.Name == null to have the same logic, otherwise in case Model.Model2.Model3.Model4.Name is null, mapped.Name will stay null
@ErikPhilips Not on the same page I guess. Please try to see what happens in both your cases if Model.Model2.Model3.Model4.Name is null.
The result is "N/A", again PLEASE READ THE FIRST COMMENT. DotNetFiddle.Net Working Example.
@ErikPhilips: That has nothing to to with the first comment, as this does not relate to your first example. In this you would jump into the else-branch and have mapped.Name = Model.Model2.Model3.Model4.Name -> mapped.Name = null, while you second example would substitute to mapped.Name = "N/A". See the edited DotNetFiddle
|
11

This is relatively new to C# which makes it easy for us to call the functions with respect to the null or non-null values in method chaining.

old way to achieve the same thing was:

var functionCaller = this.member; if (functionCaller!= null) functionCaller.someFunction(var someParam); 

and now it has been made much easier with just:

member?.someFunction(var someParam); 

I strongly recommend this doc page.

2 Comments

Quick question..var user = db.Users.Where(m=>m.id == id).FirstOrDefault(); Console.WriteLine(user?.id); Would this work or ?. only work with navigation properties? Kindly check this fiddle: dotnetfiddle.net/2BblBv
The above answer basically states this, but just for emphasis, "functionCaller" here could be "object that could have associated methods", so, if there was a cat object that has a meow() method, if you want to check to see whether cat is null prior to invoking meow(), then code it up as cat?.meow(). If cat is currently null, meow() will not be invoked.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.