Cosa significa punto interrogativo e punto operatore? intendi in C # 6.0?


359

Con C # 6.0 nell'anteprima di VS2015 abbiamo un nuovo operatore ?., che può essere usato in questo modo:

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

...

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

Che cosa fa esattamente?

Risposte:


500

È l' operatore condizionale nullo . Significa sostanzialmente:

"Valuta il primo operando; se è null, stop, con risultato null. Altrimenti, valuta il secondo operando (come accesso membro del primo operando)."

Nel tuo esempio, il punto è che, se lo aè null, a?.PropertyOfAvaluterà nullinvece di generare un'eccezione, quindi confronterà quel nullriferimento con foo(usando il ==sovraccarico della stringa ), scoprirà che non sono uguali e l'esecuzione andrà nel corpo ifdell'istruzione .

In altre parole, è così:

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

... tranne che aviene valutato solo una volta.

Nota che anche questo può cambiare il tipo di espressione. Ad esempio, considera FileInfo.Length. Questa è una proprietà di tipo long, ma se la usi con l'operatore condizionale null, finisci con un'espressione di tipo long?:

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

8
Non si chiama l' operatore condizionale null ?
SLaks

1
@SLaks: ho pensato che fosse "null condizionale" ma potrei sbagliarmi. L'ultima volta che ho controllato i documenti delle caratteristiche del linguaggio Roslyn, non è stato rinominato in nessuno dei due. Forse la fonte è l'autorità qui - controllerà.
Jon Skeet,

3
@SLaks: Sicuro. In SyntaxKind è apparentemente ConditionalAccessExpression che non è fastidiosamente nessuno dei due ...
Jon Skeet,

12
ho preferito il nome dell'operatore "Elvis": P
Ahmed ilyas,

3
Per la cronaca, ho visto cinque nomi diversi per questo operatore: navigazione sicura, null-conditional, null propagation, accesso condizionale, Elvis.
Gigi

81

Può essere molto utile quando si appiattisce una gerarchia e / o si mappano oggetti. Invece di:

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

Può essere scritto come (stessa logica di cui sopra)

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

Esempio di funzionamento di DotNetFiddle.Net .

(l' operatore ?? o null-coalescing è diverso dall'operatore ? o null condizionale ).

Può anche essere utilizzato al di fuori degli operatori di assegnazione con Action. Invece di

Action<TValue> myAction = null;

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

Può essere semplificato per:

myAction?.Invoke(TValue);

Esempio DotNetFiddle :

utilizzando il sistema;

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

    consoleWrite?.Invoke("Test 1");

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

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

Risultato:

Test 2


27
Per salvare le persone che cercano che cosa ?? è .. È l'operatore a coalescenza nulla e restituirà Nome se non è null, altrimenti restituirà "N / A".
Steve

6
@Erik Philips Penso che devi aggiungere || Model.Model2.Model3.Model4.Name == null per avere la stessa logica, altrimenti nel caso Model.Model2.Model3.Model4.Namesia null, mapped.Namerimarrànull
RazvanR

2
@ErikPhilips Non nella stessa pagina immagino. Per favore, prova a vedere cosa succede in entrambi i tuoi casi, se lo Model.Model2.Model3.Model4.Nameè null.
RazvanR,

1
Il risultato è "N / A", PER FAVORE, LEGGI IL PRIMO COMMENTO. Esempio di funzionamento di DotNetFiddle.Net .
Erik Philips,

7
@ErikPhilips: non ha nulla a che fare con il primo commento, in quanto non si riferisce al tuo primo esempio. In questo elsesalteresti nel ramo e lo avresti mapped.Name = Model.Model2.Model3.Model4.Name -> mapped.Name = null, mentre il tuo secondo esempio lo sostituirà mapped.Name = "N/A". Vedi il DotNetFiddle
derM modificato il

3

Questo è relativamente nuovo in C #, il che ci rende facile chiamare le funzioni rispetto ai valori null o non null nel concatenamento del metodo.

il vecchio modo per ottenere la stessa cosa era:

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

e ora è stato reso molto più semplice con solo:

member?.someFunction(var someParam);

Ti consiglio vivamente di leggerlo qui:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.