Что делает знак вопроса и точечный оператор?. означает в С# 6.0?

С С# 6.0 в предварительном просмотре VS2015 у нас есть новый оператор ?., который можно использовать следующим образом:

public class A {
   string PropertyOfA { get; set; }
}

...

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

Что именно он делает?

Ответ 1

Это нулевой условный оператор. Это в основном означает:

"Оценить первый операнд; если этот ноль, остановить, с результатом ноль. В противном случае, оценить второй операнд (как член доступа первого операнда)."

В вашем примере, суть в том, что если a равно null, то a?.PropertyOfA будет оценивать как null а не как исключение - тогда он будет сравнивать эту null ссылку с foo (используя строку == перегрузка) и обнаружит, что они не являются равный и выполнение войдет в тело оператора if.

Другими словами, это так:

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

... за исключением того, что a оценивается только один раз.

Обратите внимание, что это также может изменить тип выражения. Например, рассмотрим FileInfo.Length. Это свойство типа long, но если вы используете его с условным оператором null, вы получите выражение типа long? :

FileInfo fi = ...; // fi could be null
long? length = fi?.Length; // If fi is null, length will be null

Ответ 2

Это может быть очень полезно при выравнивании иерархии и/или отображении объектов. Вместо:

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;
}

Это может быть написано как (та же логика, что и выше)

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

DotNetFiddle.Net Рабочий пример.

(Оператор?? или null-coalescing отличается от оператора ? или null).

Его также можно использовать вне операторов присваивания с действием. Вместо

Action<TValue> myAction = null;

if (myAction != null)
{
  myAction(TValue);
}

Это может быть упрощено до:

myAction?.Invoke(TValue);

Пример DotNetFiddle:

используя Систему;

public class Program
{
  public static void Main()
  {
    Action<string> consoleWrite = null;

    consoleWrite?.Invoke("Test 1");

    consoleWrite = (s) => Console.WriteLine(s);

    consoleWrite?.Invoke("Test 2");
  }
}

Результат:

Тест 2

Ответ 3

Это относительно новое для С#, что позволяет нам легко вызывать функции с нулевыми или ненулевыми значениями в цепочке методов.

Старый способ добиться того же был:

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

и теперь это стало намного проще с помощью просто:

member?.someFunction(var someParam);

Я настоятельно рекомендую вам прочитать это здесь:

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

Ответ 4

Другим способом это можно использовать для операторов in-line if:

lblDueDate.Text = 
  assignment.DueDate == null ? "" : (assignment.DueDate.Value.ToShortDateString());

Выход

lblDueDate = 12/21/2021

Вместо:

if(assignment.DueDate == null)
{
    lblDueDate.Text = "";
}
else
{
    lblDueDate.Text = assignment.DueDate.ToShortDateString();
}

FYI .ToShortDateString() просто выравнивает раздражающее время с конца возвращаемого значения DateTime. Вместо 12/21/2021 05:20:00.655