Odpowiedzi:
To zerowy operator warunkowy . Zasadniczo oznacza:
„Oceń pierwszy operand; jeśli jest to null, zatrzymaj z wynikiem null. W przeciwnym razie oceń drugi operand (jako dostęp członka pierwszego operandu).”
W twoim przykładzie chodzi o to, że jeśli a
jest null
, to zamiast a?.PropertyOfA
oceny null
zgłasza wyjątek - porównuje to null
odwołanie z foo
(przy użyciu ==
przeciążenia łańcucha ), stwierdzi, że nie są one równe, a wykonanie przejdzie do treści if
instrukcji .
Innymi słowy, wygląda to tak:
string bar = (a == null ? null : a.PropertyOfA);
if (bar != foo)
{
...
}
... z wyjątkiem tego, że a
ocenia się tylko raz.
Pamiętaj, że może to również zmienić typ wyrażenia. Rozważmy na przykład FileInfo.Length
. Jest to właściwość typu long
, ale jeśli użyjesz jej z operatorem warunkowym o wartości NULL, otrzymasz wyrażenie typu long?
:
FileInfo fi = ...; // fi could be null
long? length = fi?.Length; // If fi is null, length will be null
Może być bardzo przydatny podczas spłaszczania hierarchii i / lub mapowania obiektów. Zamiast:
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;
}
Można to napisać jak (taka sama logika jak powyżej)
mapped.Name = Model.Model2?.Model3?.Model4?.Name ?? "N/A";
Przykład działania DotNetFiddle.Net .
( operator koalescencyjny? lub null jest inny niż operator warunkowy? lub null ).
Może być również używany po stronie operatorów przypisania za pomocą Action. Zamiast
Action<TValue> myAction = null;
if (myAction != null)
{
myAction(TValue);
}
Można to uprościć:
myAction?.Invoke(TValue);
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");
}
}
Wynik:
Test 2
|| Model.Model2.Model3.Model4.Name == null
mieć tę samą logikę, poza tym sprawa Model.Model2.Model3.Model4.Name
jest null
, mapped.Name
pozostanienull
Model.Model2.Model3.Model4.Name
jest null
.
else
oddziału i miałbyś mapped.Name = Model.Model2.Model3.Model4.Name -> mapped.Name = null
, podczas gdy drugi przykład zastąpiłby mapped.Name = "N/A"
. Zobacz edytowany DotNetFiddle
Jest to stosunkowo nowe w C #, co ułatwia nam wywoływanie funkcji w odniesieniu do wartości zerowej lub innej w łańcuchu metod.
starym sposobem na osiągnięcie tego samego było:
var functionCaller = this.member;
if (functionCaller!= null)
functionCaller.someFunction(var someParam);
a teraz stało się to znacznie łatwiejsze dzięki:
member?.someFunction(var someParam);
Zdecydowanie polecam przeczytać tutaj: