Что означает знак вопроса и точка оператора? значит в C # 6.0?


359

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

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

...

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

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

Ответы:


500

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

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

В вашем примере, смысл в том, что если 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

8
Разве это не называется нулевым условным оператором?
SLaks

1
@SLaks: Я думал, что это «условный ноль», но я могу ошибаться. В прошлый раз, когда я проверял документы на языке Roslyn, он также не был переименован. Может быть, источник здесь авторитет - проверим.
Джон Скит

3
@SLaks: Конечно. В SyntaxKind это, по-видимому, ConditionalAccessExpression, что, к сожалению, ни для кого из них ...
Джон Скит

12
Я предпочел имя оператора "Элвис": P
Ахмед Ильяс

3
Просто для записи я видел пять разных названий этого оператора: безопасная навигация, нулевое условие, нулевое распространение, условный доступ, Элвис.
Гиги

81

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

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


27
Чтобы спасти людей, ищущих что ?? is .. Это оператор с нулевым слиянием, который вернет Name, если он не нулевой, в противном случае он вернет "N / A".
Стив

6
@Erik Philips Я думаю , что нужно добавить , || Model.Model2.Model3.Model4.Name == null чтобы иметь ту же логику, в противном случае в случае , если Model.Model2.Model3.Model4.Nameесть null, mapped.Nameостанетсяnull
RazvanR

2
@ErikPhilips Не на той же странице, я думаю. Пожалуйста, попробуйте посмотреть, что происходит в обоих ваших случаях, если Model.Model2.Model3.Model4.Nameесть null.
RazvanR

1
Результат "N / A", снова ПОЖАЛУЙСТА, ПРОЧИТАЙТЕ ПЕРВЫЙ КОММЕНТАРИЙ. DotNetFiddle.Net Рабочий пример .
Эрик Филипс

7
@ErikPhilips: Это не имеет ничего общего с первым комментарием, поскольку это не относится к вашему первому примеру. В этом случае вы перейдете в elseветвь и получите mapped.Name = Model.Model2.Model3.Model4.Name -> mapped.Name = null, а второй пример заменит mapped.Name = "N/A". См. Отредактированный DotNetFiddle
derM

3

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

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.