Zieltypisierte new
-Ausdrücke
Anmerkung
Dieser Artikel ist eine Featurespezifikation. 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 Featurespezifikation und der abgeschlossenen Implementierung geben. Diese Unterschiede werden in den entsprechenden Hinweisen zum Language Design Meeting (LDM) erfasst.
Weitere Informationen zum Einführen von Featurespezifikationen in den C#-Sprachstandard finden Sie im Artikel zu den Spezifikationen.
Champion Issue: https://github.com/dotnet/csharplang/issues/100
Zusammenfassung
Geben Sie keine Typspezifikation für Konstruktoren an, wenn der Typ bekannt ist.
Motivation
Die Feldinitialisierung zulassen, ohne den Typ zu duplizieren.
Dictionary<string, List<int>> field = new() {
{ "item1", new() { 1, 2, 3 } }
};
Lassen Sie das Auslassen des Typs zu, wenn er von der Verwendung abgeleitet werden kann.
XmlReader.Create(reader, new() { IgnoreWhitespace = true });
Instanziieren Sie ein Objekt, ohne den Typ anzugeben.
private readonly static object s_syncObj = new();
Spezifikation
Eine neue syntaktische Form, target_typed_new des object_creation_expression wird akzeptiert, bei der der type optional ist.
object_creation_expression
: 'new' type '(' argument_list? ')' object_or_collection_initializer?
| 'new' type object_or_collection_initializer
| target_typed_new
;
target_typed_new
: 'new' '(' argument_list? ')' object_or_collection_initializer?
;
Ein target_typed_new Ausdruck hat keinen Typ. Es gibt jedoch eine neue Objekterzeugung Konversion, die eine implizite Konversion von Ausdruck ist, die von einem target_typed_new zu jedem Typ existiert.
Für einen Zieltyp T
ist der Typ T0
der zugrundeliegende Typ von T
, wenn T
eine Instanz von System.Nullable
ist. Andernfalls wird T0
T
. Die Bedeutung eines target_typed_new Ausdrucks, der in den Typ konvertiert wirdT
entspricht der Bedeutung einer entsprechenden object_creation_expression, die T0
als Typ angibt.
Es handelt sich um einen Kompilierungsfehler, wenn ein target_typed_new als Operand eines unären oder binären Operators verwendet wird, oder wenn er dort benutzt wird, wo er nicht einer Objekterstellungskonvertierungunterliegt.
Offene Frage: Sollten wir Delegaten und Tupel als Ziel-Typ zulassen?
Die obigen Regeln schließen Delegates (ein Referenztyp) und Tuples (ein Struct-Typ) ein. Obwohl beide Typen konstruierbar sind, kann, wenn der Typ ableitbar ist, bereits eine anonyme Funktion oder ein Tupel-Literal verwendet werden.
(int a, int b) t = new(1, 2); // "new" is redundant
Action a = new(() => {}); // "new" is redundant
(int a, int b) t = new(); // OK; same as (0, 0)
Action a = new(); // no constructor found
Verschiedenes
Es folgen Folgen der Spezifikation:
throw new()
ist zulässig (der Zieltyp istSystem.Exception
)- Der Ziel-Typ
new
ist bei binären Operatoren nicht zugelassen. - Es ist unzulässig, wenn es keinen Typ als Ziel gibt: unäre Operatoren, Sammlung eines
foreach
, in einemusing
, in einer Dekonstruktion, in einemawait
-Ausdruck, als anonyme Typeigenschaft (new { Prop = new() }
), in einerlock
-Anweisung, in einersizeof
, in einerfixed
-Anweisung, in einem Mitgliedszugriff (new().field
), in einer dynamisch ausgelieferten Operation (someDynamic.Method(new())
), in einer LINQ-Abfrage, als Operand desis
-Operators, als linker Operand des??
-Operators, ... - Es ist auch als
ref
nicht zulässig. - Die folgenden Arten von Typen sind nicht als Ziele der Konvertierung zulässig.
- Enum-Typen:
new()
funktionieren (danew Enum()
funktioniert, um den Standardwert zu geben), abernew(1)
funktioniert nicht, da Enum-Typen keinen Konstruktor haben. - Schnittstellentypen: Dies funktioniert genauso wie der entsprechende Erstellungsausdruck für COM-Typen.
- Array-Typen: Arrays benötigen eine spezielle Syntax, um die Länge anzugeben.
- Dynamisch: wir lassen
new dynamic()
nicht zu, also bieten wir keine Möglichkeitnew()
mitdynamic
als Zieltyp. - Tupel: Diese haben die gleiche Bedeutung wie eine Objekterzeugung unter Verwendung des zugrunde liegenden Typs.
- Alle anderen Typen, die in der object_creation_expression nicht zulässig sind, werden ebenfalls ausgeschlossen, z. B. Zeigertypen.
- Enum-Typen:
Nachteile
Es gab einige Bedenken, dass der Zieltyp new
neue Kategorien von fehlerhaften Änderungen erstellt, aber das haben wir bereits mit null
und default
, und das war kein großes Problem.
Alternativen
Die meisten Beschwerden darüber, dass Typen zu lang sind, um sie in der Feldinitialisierung zu duplizieren, beziehen sich auf Typargumente und nicht auf den Typ selbst. Wir könnten nur Typargumente wie new Dictionary(...)
(oder ähnlich) ableiten und Typargumente lokal aus Argumenten oder dem Collection Initializer ableiten.
Fragen
- Sollten wir Verwendungen in Ausdrucksbäumen verbieten? (nein)
- Wie interagiert das Feature mit
dynamic
Argumenten? (keine Spezielle Behandlung) - Wie Soll IntelliSense mit
new()
arbeiten? (nur wenn ein einzelner Zieltyp vorhanden ist)
Planungsbesprechungen
C# feature specifications