Bin über diese Codezeile gelaufen:
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
Was bedeuten die beiden Fragezeichen, ist es eine Art ternärer Operator? Es ist schwer, in Google nachzuschlagen.
Bin über diese Codezeile gelaufen:
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
Was bedeuten die beiden Fragezeichen, ist es eine Art ternärer Operator? Es ist schwer, in Google nachzuschlagen.
Antworten:
Es ist der Null-Koaleszenz-Operator und ganz ähnlich dem ternären (Sofort-Wenn-) Operator. Siehe auch ?? Betreiber - MSDN .
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
erweitert sich zu:
FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();
was sich weiter ausdehnt auf:
if(formsAuth != null)
FormsAuth = formsAuth;
else
FormsAuth = new FormsAuthenticationWrapper();
Auf Englisch bedeutet dies: "Wenn das, was links ist, nicht null ist, verwenden Sie das, andernfalls verwenden Sie das, was rechts ist."
Beachten Sie, dass Sie eine beliebige Anzahl davon nacheinander verwenden können. Die folgende Anweisung weist die erste Nicht-Null Answer#
zu Answer
(wenn alle Antworten null sind, Answer
ist die null):
string Answer = Answer1 ?? Answer2 ?? Answer3 ?? Answer4;
Erwähnenswert ist auch, dass die obige Erweiterung zwar konzeptionell äquivalent ist, das Ergebnis jedes Ausdrucks jedoch nur einmal ausgewertet wird. Dies ist wichtig, wenn ein Ausdruck beispielsweise ein Methodenaufruf mit Nebenwirkungen ist. (Dank an @Joey für den Hinweis.)
??
bleibt assoziativ, a ?? b ?? c ?? d
entspricht also ((a ?? b) ?? c ) ?? d
. "Die Zuweisungsoperatoren und der ternäre Operator (? :) sind rechtsassoziativ. Alle anderen binären Operatoren sind linksassoziativ." Quelle: msdn.microsoft.com/en-us/library/ms173145.aspx
Nur weil noch niemand die magischen Worte gesagt hat: Es ist der Null-Koaleszenz-Operator . Es ist in Abschnitt 7.12 der C # 3.0-Sprachspezifikation definiert .
Es ist sehr praktisch, insbesondere aufgrund der Funktionsweise, wenn es in einem Ausdruck mehrmals verwendet wird. Ein Ausdruck der Form:
a ?? b ?? c ?? d
gibt das Ergebnis des Ausdrucks aus, a
wenn es nicht null ist, andernfalls versuchen b
, andernfalls versuchen c
, andernfalls versuchen d
. Es schließt an jedem Punkt kurz.
Wenn der Typ von d
nicht nullbar ist, ist auch der Typ des gesamten Ausdrucks nicht nullwertfähig.
Es ist der Null-Koaleszenz-Operator.
http://msdn.microsoft.com/en-us/library/ms173224.aspx
Ja, fast unmöglich zu suchen, wenn Sie nicht wissen, wie es heißt! :-)
EDIT: Und das ist eine coole Funktion aus einer anderen Frage. Sie können sie verketten.
Vielen Dank an alle, hier ist die prägnanteste Erklärung, die ich auf der MSDN-Website gefunden habe:
// y = x, unless x is null, in which case y = -1.
int y = x ?? -1;
-1
ist nur eine Ebene int
, die nicht nullwertfähig ist).
x
es vom Typ ist int?
, aber y
vom Typ int
, können Sie schreiben int y = (int)(x ?? -1)
. Es wird analysiert x
, int
wenn dies nicht der Fall ist null
, oder zugewiesen -1
, y
wenn dies der Fall x
ist null
.
Die beiden Fragezeichen (??) zeigen an, dass es sich um einen Coalescing-Operator handelt.
Der Koaleszenzoperator gibt den ersten NON-NULL-Wert aus einer Kette zurück. Sie können dieses Youtube-Video sehen, das das Ganze praktisch demonstriert.
Aber lassen Sie mich noch mehr zu dem hinzufügen, was das Video sagt.
Wenn Sie die englische Bedeutung der Verschmelzung sehen, heißt es "zusammen konsolidieren". Im Folgenden finden Sie beispielsweise einen einfachen Koaleszenzcode, der vier Zeichenfolgen verkettet.
Also , wenn str1
ist null
es versuchen str2
, wenn str2
ist null
wird es versuchen , str3
und so weiter , bis er eine Saite mit einem Nicht-Null - Wert findet.
string final = str1 ?? str2 ?? str3 ?? str4;
Mit einfachen Worten, der Coalescing-Operator gibt den ersten NON-NULL-Wert aus einer Kette zurück.
Es ist eine kurze Hand für den ternären Operator.
FormsAuth = (formsAuth != null) ? formsAuth : new FormsAuthenticationWrapper();
Oder für diejenigen, die nicht ternär sind:
if (formsAuth != null)
{
FormsAuth = formsAuth;
}
else
{
FormsAuth = new FormsAuthenticationWrapper();
}
!= null
) als auch der zweite formsAuth
(nach dem ?
) geändert werden. In der Null-Koaleszenz-Form nehmen beide implizit die von Ihnen angegebenen Werte an.
Wenn Sie mit Ruby vertraut sind, ||=
scheint ??
es mir C # zu ähneln. Hier ist etwas Ruby:
irb(main):001:0> str1 = nil
=> nil
irb(main):002:0> str1 ||= "new value"
=> "new value"
irb(main):003:0> str2 = "old value"
=> "old value"
irb(main):004:0> str2 ||= "another new value"
=> "old value"
irb(main):005:0> str1
=> "new value"
irb(main):006:0> str2
=> "old value"
Und in C #:
string str1 = null;
str1 = str1 ?? "new value";
string str2 = "old value";
str2 = str2 ?? "another new value";
x ||= y
Desugars zu so etwas wie x = x || y
, ??
ist also eigentlich eher einfach ||
in Ruby.
??
nur Sorgen über null
, während der ||
Betreiber in Ruby, wie in den meisten Sprachen, mehr über ist null
, false
oder alles , was ein boolean mit einem Wert von betrachtet werden kann false
(zB in einigen Sprachen ""
). Dies ist keine gute oder schlechte Sache, nur ein Unterschied.
Daran ist nichts Gefährliches. In der Tat ist es schön. Sie können einen Standardwert hinzufügen, wenn dies wünschenswert ist, zum Beispiel:
CODE
int x = x1 ?? x2 ?? x3 ?? x4 ?? 0;
int? x1 = null;
Ist das richtig
x1
- x4
MUSS nullfähige Typen sein: Es macht keinen Sinn, effektiv zu sagen: "Das Ergebnis ist, 0
wenn x4
es sich um einen Wert handelt, den es unmöglich annehmen kann" ( null
). "Nullable type" umfasst hier natürlich sowohl nullable value- Typen als auch Referenztypen. Es ist ein Fehler beim Kompilieren, wenn eine oder mehrere der verketteten Variablen (mit Ausnahme der letzten) nicht nullwertfähig sind.
Wie in zahlreichen Antworten richtig angegeben, handelt es sich um den "Null-Koaleszenz-Operator" ( ?? ), von dem Sie vielleicht auch seinen Cousin, den "Null-bedingten Operator" ( ?. Oder ? [ ), Der ein Operator ist, überprüfen möchten oft wird es in Verbindung mit verwendet ?
Wird verwendet, um vor dem Ausführen einer Mitgliedszugriffs- ( ?. ) Oder Indexoperation ( ? [ ) Auf Null zu testen . Mit diesen Operatoren können Sie weniger Code schreiben, um Nullprüfungen durchzuführen, insbesondere beim Abstieg in Datenstrukturen.
Zum Beispiel:
// if 'customers' or 'Order' property or 'Price' property is null,
// dollarAmount will be 0
// otherwise dollarAmount will be equal to 'customers.Order.Price'
int dollarAmount = customers?.Order?.Price ?? 0;
der alte Weg ohne ? und ?? dies zu tun ist
int dollarAmount = customers != null
&& customers.Order!=null
&& customers.Order.Price!=null
? customers.Order.Price : 0;
Das ist ausführlicher und umständlicher.
Nur zu Ihrer Unterhaltung (zu wissen, dass Sie alle C # -Typen sind ;-).
Ich denke, es hat seinen Ursprung in Smalltalk, wo es es schon seit vielen Jahren gibt. Es ist dort definiert als:
im Objekt:
? anArgument
^ self
in UndefinedObject (auch bekannt als Nullklasse):
? anArgument
^ anArgument
Es gibt sowohl evaluierende (?) Als auch nicht evaluierende Versionen (??) davon.
Es wird häufig in Getter-Methoden für faul initialisierte private (Instanz-) Variablen gefunden, die bis zur tatsächlichen Verwendung gleich Null bleiben.
Einige der hier aufgeführten Beispiele zum Abrufen von Werten mithilfe der Koaleszenz sind ineffizient.
Was Sie wirklich wollen, ist:
return _formsAuthWrapper = _formsAuthWrapper ?? new FormsAuthenticationWrapper();
oder
return _formsAuthWrapper ?? (_formsAuthWrapper = new FormsAuthenticationWrapper());
Dies verhindert, dass das Objekt jedes Mal neu erstellt wird. Anstatt dass die private Variable null bleibt und bei jeder Anforderung ein neues Objekt erstellt wird, wird sichergestellt, dass die private Variable zugewiesen wird, wenn das neue Objekt erstellt wird.
??
Abkürzung nicht ausgewertet? new FormsAuthenticationWrapper();
wird genau dann ausgewertet, wenn_formsAuthWrapper
Null ist.
Ich habe diesen ganzen Thread und viele andere gelesen, aber ich kann keine so gründliche Antwort finden wie diese.
Womit ich das "Warum zu verwenden? Und wann zu verwenden? Und wie zu verwenden?" Vollständig verstand.
Windows-Kommunikationsgrundlage entfesselt Von Craig McMurtry ISBN 0-672-32948-4
Es gibt zwei häufige Umstände, unter denen man wissen möchte, ob einer Instanz eines Wertetyps ein Wert zugewiesen wurde. Die erste ist, wenn die Instanz einen Wert in einer Datenbank darstellt. In einem solchen Fall möchte man die Instanz untersuchen können, um festzustellen, ob tatsächlich ein Wert in der Datenbank vorhanden ist. Der andere Umstand, der für den Gegenstand dieses Buches relevanter ist, besteht darin, dass die Instanz ein Datenelement darstellt, das von einer entfernten Quelle empfangen wurde. Auch hier möchte man aus der Instanz ermitteln, ob ein Wert für dieses Datenelement empfangen wurde.
Das .NET Framework 2.0 enthält eine generische Typdefinition, die Fälle wie diese vorsieht, in denen einer Instanz eines Wertetyps null zugewiesen werden soll und geprüft werden soll, ob der Wert der Instanz null ist. Diese generische Typdefinition ist System.Nullable, wodurch die generischen Typargumente, die T ersetzen können, auf Werttypen beschränkt werden. Instanzen von Typen, die aus System.Nullable erstellt wurden, können den Wert null erhalten. In der Tat sind ihre Werte standardmäßig null. Aus System.Nullable erstellte Typen können daher als nullbare Werttypen bezeichnet werden. System.Nullable hat die Eigenschaft Value, mit der der einer Instanz eines daraus erstellten Typs zugewiesene Wert abgerufen werden kann, wenn der Wert der Instanz nicht null ist. Daher kann man schreiben:
System.Nullable<int> myNullableInteger = null;
myNullableInteger = 1;
if (myNullableInteger != null)
{
Console.WriteLine(myNullableInteger.Value);
}
Die Programmiersprache C # bietet eine abgekürzte Syntax zum Deklarieren von Typen, die aus System.Nullable erstellt wurden. Diese Syntax erlaubt es, abzukürzen:
System.Nullable<int> myNullableInteger;
zu
int? myNullableInteger;
Der Compiler verhindert, dass einer versucht, den Wert eines nullbaren Werttyps einem normalen Werttyp auf folgende Weise zuzuweisen:
int? myNullableInteger = null;
int myInteger = myNullableInteger;
Dies wird verhindert, da der nullbare Werttyp den Wert null haben könnte, den er in diesem Fall tatsächlich hätte, und dieser Wert keinem normalen Werttyp zugewiesen werden kann. Obwohl der Compiler diesen Code zulassen würde,
int? myNullableInteger = null;
int myInteger = myNullableInteger.Value;
Die zweite Anweisung würde dazu führen, dass eine Ausnahme ausgelöst wird, da jeder Versuch, auf die Eigenschaft System.Nullable.Value zuzugreifen, eine ungültige Operation ist, wenn dem aus System.Nullable erstellten Typ kein gültiger Wert von T zugewiesen wurde, was in diesem Fall nicht geschehen ist Fall.
Eine geeignete Methode zum Zuweisen des Werts eines nullbaren Werttyps zu einem normalen Werttyp besteht darin, mithilfe der System.Nullable.HasValue-Eigenschaft festzustellen, ob dem nullbaren Werttyp ein gültiger Wert von T zugewiesen wurde:
int? myNullableInteger = null;
if (myNullableInteger.HasValue)
{
int myInteger = myNullableInteger.Value;
}
Eine andere Option ist die Verwendung dieser Syntax:
int? myNullableInteger = null;
int myInteger = myNullableInteger ?? -1;
Womit der gewöhnlichen Ganzzahl myInteger der Wert der nullbaren Ganzzahl "myNullableInteger" zugewiesen wird, wenn dieser ein gültiger Ganzzahlwert zugewiesen wurde; Andernfalls wird myInteger der Wert -1 zugewiesen.
Es ist ein Null-Koaleszenz-Operator, der ähnlich wie ein ternärer Operator funktioniert.
a ?? b => a !=null ? a : b
Ein weiterer interessanter Punkt hierfür ist: "Ein nullfähiger Typ kann einen Wert enthalten oder undefiniert sein" . Wenn Sie also versuchen, einem nicht nullbaren Werttyp einen nullbaren Werttyp zuzuweisen, wird ein Fehler bei der Kompilierung angezeigt.
int? x = null; // x is nullable value type
int z = 0; // z is non-nullable value type
z = x; // compile error will be there.
Also, um das mit ?? Operator:
z = x ?? 1; // with ?? operator there are no issues
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
ist äquivalent zu
FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();
Aber das Coole daran ist, dass man sie verketten kann, wie andere Leute sagten. Das einzige, was nicht angesprochen wird, ist, dass Sie es tatsächlich verwenden können, um eine Ausnahme auszulösen.
A = A ?? B ?? throw new Exception("A and B are both NULL");
Der ??
Operator wird als Null-Koaleszenz-Operator bezeichnet. Es gibt den linken Operanden zurück, wenn der Operand nicht null ist. Andernfalls wird der rechte Operand zurückgegeben.
int? variable1 = null;
int variable2 = variable1 ?? 100;
Auf variable2
den Wert setzen variable1
, wenn variable1
NICHT null ist; Andernfalls, wenn variable1 == null
, eingestellt variable2
auf 100.
Andere haben das Null Coalescing Operator
ganz gut beschrieben. Für Interessierte gibt es eine verkürzte Syntax, wo dies (die SO-Frage):
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
ist gleichbedeutend damit:
FormsAuth ??= new FormsAuthenticationWrapper();
Einige finden es lesbarer und prägnanter.