In C # -Generika können wir eine Einschränkung für einen Typparameter deklarieren T
, um einen Standardkonstruktor zu haben, indem wir sagen where T : new()
. Es sind jedoch keine anderen Arten von Einschränkungen wie diese gültig - new(string)
zum Beispiel usw.
Was ist der Grund aus Sicht des Sprachdesigns und / oder der Implementierung?
Gibt es etwas in der Art und Weise, wie Konstruktoren arbeiten, oder in der Art und Weise, wie das Typsystem implementiert ist, das dies verbietet (oder zumindest erschwert)? Wenn ja, was ist das? Ich erinnere mich irgendwo zu lesen , die default(T)
kompiliert eigentlich new T()
für T : struct
. Hat es vielleicht damit zu tun?
Oder ist es einfach eine gestalterische Entscheidung, um die Sprache nicht zu kompliziert zu machen?
quelle
new(string)
ist keine Standard-Konstruktor-Einschränkung. Ihre Frage lautet gleichbedeutend mit "Warum gibt es keine Einschränkungen, die bestimmte Konstruktorsignaturen erfordern?" Sehr wahrscheinlich, weil eine solche Einschränkung nicht besonders nützlich wäre.Antworten:
Als verbindliche Antwort verweise ich auf Eric Lipperts Antwort auf diese Frage zu StackOverflow vor einigen Jahren, von der ein Ausschnitt im Folgenden kurz zitiert wird.
quelle
Das Dekompilieren (gemäß dem Vorschlag von Robert Harvey) ergab für alle Interessierten Folgendes. Diese Methode:
Anscheinend wird beim Kompilieren Folgendes:
T
es sich um einen Werttyp handelt,new()
wirddefault(T)
.T
es sich um einen Referenztyp handelt, wirdnew()
die Reflexion verwendet.Activator.CreateInstance()
Intern anruftRuntimeType.CreateInstanceDefaultCtor()
.Es ist also so - intern sind Standardkonstruktoren in Bezug auf die CLR wirklich etwas Besonderes für C #. Anderen Konstruktoren die gleiche Behandlung zu geben, wäre kostspielig gewesen, selbst wenn es einige gültige Anwendungsfälle für kompliziertere Einschränkungen in Generika gibt.
quelle
default(T)
für Werttypen?t
Variable (die durch verschachteltereturn
Anweisungen ersetzt werden könnte ).