Was bedeutet Fragezeichen und Punktoperator? Mittelwert in C # 6.0?


359

Mit C # 6.0 in der VS2015-Vorschau haben wir einen neuen Operator ?., der wie folgt verwendet werden kann:

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

...

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

Was genau macht es?

Antworten:


500

Es ist der nullbedingte Operator. Es bedeutet im Grunde:

"Bewerten Sie den ersten Operanden. Wenn dies null ist, stoppen Sie mit dem Ergebnis null. Andernfalls bewerten Sie den zweiten Operanden (als Elementzugriff des ersten Operanden)."

In Ihrem Beispiel, dass der Punkt ist , wenn aist null, dann a?.PropertyOfAzu bewerten , wird nulleher als eine Ausnahme zu werfen - es wird dann das Vergleichen nullVerweis mit foo(string die mit ==Überlast), finden sie nicht gleich sind und die Ausführung wird der Körper der gehen in ifAussage .

Mit anderen Worten, es ist so:

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

... außer dass anur einmal ausgewertet wird.

Beachten Sie, dass dies auch den Typ des Ausdrucks ändern kann. Betrachten Sie zum Beispiel FileInfo.Length. Das ist eine Eigenschaft vom Typ long, aber wenn Sie sie mit dem bedingten Nulloperator verwenden, erhalten Sie einen Ausdruck vom Typ long?:

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

8
Wird es nicht als nullbedingter Operator bezeichnet?
SLaks

1
@SLaks: Ich dachte, es wäre "bedingte Null", aber ich könnte mich irren. Als ich das letzte Mal die Dokumente zu den Roslyn-Sprachfunktionen überprüft habe, wurde sie auch nicht umbenannt. Vielleicht ist die Quelle die Autorität hier - wird überprüfen.
Jon Skeet

3
@ Slaks: Sicher. In SyntaxKind ist es anscheinend ConditionalAccessExpression, was ärgerlicherweise keiner von beiden ist ...
Jon Skeet

12
Ich bevorzugte den Namen "Elvis" Betreiber: P
Ahmed Ilyas

3
Nur zur Veranschaulichung Ich habe fünf verschiedene Namen für diesen Operator gesehen: sichere Navigation, null-bedingt, null-Weitergabe, bedingter Zugriff, Elvis.
Gigi

81

Dies kann sehr nützlich sein, wenn Sie eine Hierarchie reduzieren und / oder Objekte zuordnen. Anstatt:

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

Es kann wie folgt geschrieben werden (gleiche Logik wie oben)

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

DotNetFiddle.Net Arbeitsbeispiel .

(die ?? oder Null-Koaleszenz Operator ist anders als die ? oder null Bedingungsoperator ).

Es kann auch außerhalb von Zuweisungsoperatoren mit Aktion verwendet werden. Anstatt

Action<TValue> myAction = null;

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

Es kann vereinfacht werden zu:

myAction?.Invoke(TValue);

DotNetFiddle Beispiel :

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

Ergebnis:

Test 2


27
Um Menschen zu retten, die nachsehen, was zum ?? is .. Es ist der Null-Koaleszenz-Operator und gibt Name zurück, wenn er nicht null ist, andernfalls wird "N / A" zurückgegeben.
Steve

6
@Erik Philips Ich glaube , Sie hinzufügen müssen || Model.Model2.Model3.Model4.Name == null die gleiche Logik zu haben, sonst Fall Model.Model2.Model3.Model4.Nameist null, mapped.Namewird bleibennull
RazvanR

2
@ErikPhilips Nicht auf der gleichen Seite, denke ich. Bitte versuchen Sie zu sehen, was in beiden Fällen passiert, wenn dies der Fall Model.Model2.Model3.Model4.Nameist null.
RazvanR

1
Das Ergebnis ist "N / A". BITTE LESEN SIE DEN ERSTEN KOMMENTAR. DotNetFiddle.Net Arbeitsbeispiel .
Erik Philips

7
@ErikPhilips: Das hat nichts mit dem ersten Kommentar zu tun, da dies nicht mit Ihrem ersten Beispiel zusammenhängt. In diesem würden Sie in die else-zweig springen und haben mapped.Name = Model.Model2.Model3.Model4.Name -> mapped.Name = null, während Ihr zweites Beispiel ersetzen würde mapped.Name = "N/A". Siehe die bearbeitete DotNetFiddle
derM

3

Dies ist für C # relativ neu, was es uns leicht macht, die Funktionen in Bezug auf die Null- oder Nicht-Null- Werte in der Methodenverkettung aufzurufen.

Der alte Weg, dasselbe zu erreichen, war:

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

und jetzt ist es viel einfacher geworden mit nur:

member?.someFunction(var someParam);

Ich empfehle Ihnen dringend, es hier zu lesen:

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.