Ich drücke auf "Warum nicht" -Fragen zurück, weil die Antworten zunächst fast nie zufriedenstellend sind - Sie haben bereits die Antwort erhalten: "Die Funktion ist nicht so, wie Sie es möchten, weil die Spezifikation nicht sagt, was Sie sagen möchten." , was ich mir nicht besonders befriedigend vorstelle. Zweitens muss das Designteam nicht rechtfertigen, warum die Welt nicht ist wie Sie es möchten. Funktionen existieren nicht kostenlos und werden dann außerhalb der Sprache entworfen. Vielmehr müssen Features zuerst begründet und dann in entworfen werden.
Versuchen wir also, Ihre "Warum nicht" -Frage etwas klarer zu gestalten. Das vorhandene Merkmal ist "ein Array-Initialisierer kann verwendet werden (a) auf der rechten Seite der Gleichheit in einer Initialisierung oder (b) rechts von einer Objektkonstruktion vom Array-Typ." Das vorgeschlagene Merkmal ist: "Ein Array-Initialisierer kann auch als Ausdruck verwendet werden". Die Frage ist: "Welche Kritik würde Eric an dem vorgeschlagenen Feature üben?"
Die erste Kritik, die ich machen würde, ist, dass es unklar ist, was die Art des Ausdrucks ist. In einem Variableninitialisierer haben Sie den Typ der Variablen und in einem Objekterstellungsausdruck haben Sie den Typ des Objekts; Aus beiden können wir den Typ des konstruierten Arrays ableiten. Welchen Typ sollten wir ohne einen Hinweis ableiten?
In C # 1.0 wurden beim Hinzufügen dieser Funktion insgesamt null Inferenzen vom Typ Typ in der Sprache vorgenommen. Ein Designprinzip in den frühen Tagen von C # war "keine Überraschungen" und dass der Compiler nicht "zu schlau" war. Wenn der Entwickler beabsichtigt, dass ein Ausdruck von einem bestimmten Typ ist, sollte dieser Typ im Ausdruck auf irgendeine Weise offensichtlich sein. Wenn du sagst
new double[] { 1, 2, 3.4 }
es ist ziemlich klar, welcher Typ beabsichtigt ist. Ähnlich
new Animal[] { cat, dog, null }
Das vorgeschlagene Merkmal verstößt gegen dieses Prinzip. Der Ausdruck muss einen Typ haben, aber es ist keineswegs klar, in welchem Typ sich das Argument befindet
M({cat, dog, null})
Außerdem: Nehmen wir an M, wir haben zwei Überladungen von , von denen eine ein Array von Animalund eine ein Array von nimmt IPet. Welche Überlastung vonM ist anwendbar? Ist eine der Konvertierungen besser als die andere? Die Arten der Elemente sind CatundDog ; Ist es sinnvoll, einen Typ abzuleiten, der dort nicht einmal vorkommt? Dies sind alles Fragen, die vom Designteam berücksichtigt werden müssen, und dies sind Fragen, die keineswegs offensichtliche Antworten haben. Das vorgeschlagene Merkmal führt uns in relativ kurzer Zeit in tiefe Gewässer.
Jetzt löst C # 3.0 dieses Problem, da C # 3.0 zahlreiche Funktionen hinzugefügt hat, bei denen der Compiler im Auftrag des Entwicklers Typen ableitet. Die früheren Prinzipien über "keine Überraschungen" und "einfache Regeln" standen im Widerspruch zu anderen Designprinzipien, die erforderlich sind, damit LINQ funktioniert. Sollte die von Ihnen vorgeschlagene Funktion in C # 3.0 hinzugefügt worden sein?
Es könnte sein. Die in C # 3.0 tatsächlich hinzugefügte Funktion war:
new[] { x, y, z }
leitet den Typ des Arrays mithilfe des Algorithmus ab: Nehmen Sie die Ausdrücke für Elemente mit Typen, bestimmen Sie, welcher dieser Typen der eindeutigste allgemeinste Typ ist, in den alle anderen Ausdrücke konvertierbar sind, und wählen Sie diesen aus, wenn ein solcher Typ vorhanden ist. Andernfalls entsteht ein Fehler,
Diese Funktion hätte weiter gelockert werden können, um die new[]Option zu aktivieren. Dies wurde nicht getan.
Wenn Sie mich im C # 3.0-Zeitrahmen gebeten hätten, die vorgeschlagene Funktion zu kritisieren, hätte ich darauf hingewiesen, dass (1) der C # 3.0-Compiler bereits in großer Gefahr war, den Zeitplan für die gesamte Version zu verschieben. Fügen wir also keine weiteren hinzu Design-, Implementierungs- und Testaufwand für eine völlig unnötige Funktion, die dem Benutzer sechs Tastenanschläge erspart , und (2) C # 3.0 fügte außerdem Sammlungsinitialisierer hinzu:
new List<int>() { 10, 20, 30 }
Warum sollte {10, 20, 30}automatisch ein Array sein ? Warum sollte es nicht ein sein List<int>? Oder einer von mehreren anderen Typen? Warum die Tendenz zu Arrays? Denken Sie daran, sobald wir uns entschieden haben, die Syntax für Arrays zu verankern, bleiben wir für immer dabei . Es kann sein , dass es nie etwas anderes ist, daher ist das vorgeschlagene Merkmal nicht nur unnötig, sondern verhindert auch mögliche zukünftige Merkmale, die plausibel erscheinen.
Zusammenfassend lässt sich sagen, dass die vorgeschlagene Funktion einige der Entwurfsprinzipien von C # 1.0 direkt verletzt hat. C # 3.0 wird dadurch nur unnötig belastet. In allen Versionen der Sprache seit C # 3.0 hat die vorgeschlagene Funktion kein gutes Argument, um zu empfehlen, Zeit, Mühe und Geld für viele andere würdigere Funktionen aufzuwenden.
Daher keine solche Funktion.