Що означає знак запитання та оператор крапок ?. означає в 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
}

Що саме це робить?

Відповіді:


499

Це нульовий умовний оператор. Це в основному означає:

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

У вашому прикладі справа в тому, що якщо aє null, то a?.PropertyOfAоцінюватимемо, nullа не викидати виняток - тоді вона порівняє nullпосилання з foo(використовуючи ==перевантаження рядка ), знайде, що вони не рівні, і виконання перейде в тіло ifоператора .

Іншими словами, це так:

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

... крім того, що aоцінюється лише один раз.

Зауважте, що це також може змінити тип виразу. Наприклад, розглянемо FileInfo.Length. Це властивість типу long, але якщо ви використовуєте його з нульовим умовним оператором, ви отримуєте вираз типу long?:

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

8
Це не називається нульовим умовним оператором?
Слакс

1
@SLaks: Я думав, що це "умовна сума", але я можу помилитися. Востаннє, коли я перевіряв документи мови мови Рослін, її не було перейменовано на жоден Можливо, джерело тут є авторитетом - перевірять.
Джон Скіт

3
@SLaks: Звичайно. У SyntaxKind це, мабуть, ConditionalAccessExpression, що дратує жодного з них ...
Jon Skeet

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. Замість

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
Щоб врятувати людей, які шукають, що ?? є .. Це оператор, що поєднує null, і поверне ім'я, якщо воно не є null, інакше поверне "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
Результат "Н / З", знову ж таки ПРОЧИТАТИ ПЕРШИЙ КОМЕНТАР. Приклад роботи DotNetFiddle.Net .
Ерік Філіпс

7
@ErikPhilips: Це не має відношення до першого коментаря, оскільки це не стосується вашого першого прикладу. У цьому ви стрибнете в else-развет і маєте mapped.Name = Model.Model2.Model3.Model4.Name -> mapped.Name = null, тоді як ви другий приклад замінили б mapped.Name = "N/A". Дивіться відредагований DotNetFiddle
дерм

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.