What does question mark and dot operator ?. mean i

2019-01-01 03:50发布

问题:

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?

回答1:

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


回答2:

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



回答3:

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 you to read it here:

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