Freigeben über


NULL-Sammelzuweisung

Hinweis

Dieser Artikel ist eine Feature-Spezifikation. Die Spezifikation dient als Designdokument für das Feature. Es enthält vorgeschlagene Spezifikationsänderungen sowie Informationen, die während des Entwurfs und der Entwicklung des Features erforderlich sind. Diese Artikel werden veröffentlicht, bis die vorgeschlagenen Spezifikationsänderungen abgeschlossen und in die aktuelle ECMA-Spezifikation aufgenommen werden.

Es kann einige Abweichungen zwischen der Feature-Spezifikation und der abgeschlossenen Implementierung geben. Diese Unterschiede werden in den entsprechenden Hinweisen zum Language Design Meeting (LDM) erfasst.

Weitere Informationen zum Prozess für die Aufnahme von Funktions-Speclets in den C#-Sprachstandard finden Sie im Artikel zu den Spezifikationen.

Champion Issue: https://github.com/dotnet/csharplang/issues/34

Zusammenfassung

Vereinfacht ein gängiges Code-Muster, bei dem einer Variablen ein Wert zugewiesen wird, wenn sie null ist.

Im Rahmen dieses Vorschlags werden wir die Typanforderungen für ?? lockern, damit ein Ausdruck, dessen Typ ein nicht eingeschränkter Typparameter ist, auf der linken Seite verwendet werden kann.

Motivation

Es ist üblich, Code in der Form

if (variable == null)
{
    variable = expression;
}

Dieser Vorschlag fügt der Sprache einen nicht überladbaren binären Operator hinzu, der diese Funktion ausführt.

Es gab mindestens acht verschiedene Anfragen aus der Community für diese Funktion.

Detailliertes Design

Wir fügen eine neue Form des Zuweisungsoperators hinzu

assignment_operator
    : '??='
    ;

Dies folgt den vorhandenen semantischen Regeln für zusammengesetzte Zuordnungsoperatoren (§12.21.4), mit der Ausnahme, dass wir die Zuordnung auslassen, wenn die linke Seite nicht null ist. Die Regeln für diese Funktion lauten wie folgt.

Gegeben a ??= b,wobei A der Typ von a,ist B der Typ von b, ist und A0 der zugrundeliegende Typ von A ist, wenn A ein nullbarer Werttyp ist:

  1. Wenn A nicht existiert oder ein nicht-nullbarer Wertetyp ist, tritt ein Kompilierfehler auf.
  2. Wenn B nicht implizit in A oder A0 konvertierbar ist (wenn A0 existiert), tritt ein Kompilierfehler auf.
  3. Wenn A0 vorhanden ist und B implizit in A0konvertierbar ist und B nicht dynamisch ist, ist der Typ von a ??= bA0. a ??= b wird zur Laufzeit ausgewertet als:
    var tmp = a.GetValueOrDefault();
    if (!a.HasValue) { tmp = b; a = tmp; }
    tmp
    
    Mit der Ausnahme, dass a nur einmal ausgewertet wird.
  4. Andernfalls ist der Typ von a ??= bA. a ??= b wird zur Laufzeit wie a ?? (a = b) ausgewertet, mit dem Unterschied, dass a nur einmal ausgewertet wird.

Für die Lockerung der Typanforderungen von ??, aktualisieren wir die Spezifikation, in der es derzeit heißt, dass bei a ?? b, wobei A der Typ von aist:

  1. Wenn A existiert und kein nullbarer Typ oder ein Referenztyp ist, tritt ein Kompilierfehler auf.

Wir lockern diese Anforderung:

  1. Wenn A existiert und ein nicht-nullbarer Werttyp ist, tritt ein Kompilierungszeitfehler auf.

Dies ermöglicht es dem Null-Koaleszenzoperator, mit nicht eingeschränkten Typparametern zu arbeiten, da der nicht eingeschränkte Typparameter T existiert, kein nullbarer Typ ist und kein Verweistyp ist.

Nachteile

Wie bei jeder Sprachfunktion müssen wir uns fragen, ob die zusätzliche Komplexität der Sprache durch die zusätzliche Klarheit gerechtfertigt ist, die der Gesamtheit der C#-Programme geboten wird, die von der Funktion profitieren würden.

Alternativen

Der Programmierer kann (x = x ?? y), if (x == null) x = y;oder x ?? (x = y) manuell schreiben.

Ungelöste Fragen

  • [ ] Sollten wir auch &&= und ||= Operatoren unterstützen?

Designbesprechungen

Keine.