Відповіді:
Це нульовий умовний оператор. Це в основному означає:
"Оцініть перший операнд; якщо це недійсний, зупиніться з результатом нуля. В іншому випадку оцініть другий операнд (як членський доступ до першого операнда)."
У вашому прикладі справа в тому, що якщо 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
Це може бути дуже корисно при вирівнюванні ієрархії та / або зіставлення об'єктів. Замість:
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);
за допомогою системи;
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
|| Model.Model2.Model3.Model4.Name == null
щоб мати ту ж логіку, в іншому випадку в разі , якщо Model.Model2.Model3.Model4.Name
є null
, mapped.Name
залишитьсяnull
Model.Model2.Model3.Model4.Name
є null
.
else
-развет і маєте mapped.Name = Model.Model2.Model3.Model4.Name -> mapped.Name = null
, тоді як ви другий приклад замінили б mapped.Name = "N/A"
. Дивіться відредагований DotNetFiddle
Це відносно нове значення для C #, що дозволяє нам легко викликати функції щодо нульових чи ненульових значень у ланцюжку методів.
старий спосіб досягти того ж:
var functionCaller = this.member;
if (functionCaller!= null)
functionCaller.someFunction(var someParam);
і тепер це стало набагато простіше просто:
member?.someFunction(var someParam);
Настійно рекомендую прочитати його тут: