Warum kann nicht den C# - Konstruktor infer type?
Warum ist Typ-Inferenz nicht unterstützt für Errichter die Art und Weise ist es für generische Methoden?
public class MyType<T>
{
private readonly T field;
public MyType(T value) { field = value; }
}
var obj = new MyType(42); //why can't type inference work out that I want a MyType<int>?
Obwohl man das umgehen könnte mit einer factory-Klasse,
public class MyTypeFactory
{
public static MyType<T> Create<T>(T value)
{
return new MyType<T>(value);
}
}
var myObj = MyTypeFactory.Create(42);
Gibt es einen praktischen oder philosophischen Grund, warum der Konstruktor kann nicht unterstützt Typ-Inferenz?
Ich hatte die gleiche Frage vor zwei Jahren diese hier: stackoverflow.com/questions/45604, so technisch ist dies ein Duplikat ist. Eric ' s Antwort ist ausgezeichnet und vollständig obwohl.
Wenn Sie versuchen, übergeben Sie mehrere Klassen für eine stark typisierte Ansicht, versuchen Sie diese: return View(Tupel.Erstellen(new Person(), new Adresse()));
Dies ist die richtige Antwort meiner Meinung nach. Da es die einzige ist, die eine pragmatische Lösung. Eine Lösung, die verwendet werden können, im wirklichen Leben. Mit dem factory-pattern. Noch besser, wenn Sie Namen für Ihre Fabrik das gleiche wie Ihre generischen Typ.
Bitte Stimmen Sie für die feature-request! Vorschlag: die Konstruktor-argument Typ-Inferenz
Wenn Sie versuchen, übergeben Sie mehrere Klassen für eine stark typisierte Ansicht, versuchen Sie diese: return View(Tupel.Erstellen(new Person(), new Adresse()));
Dies ist die richtige Antwort meiner Meinung nach. Da es die einzige ist, die eine pragmatische Lösung. Eine Lösung, die verwendet werden können, im wirklichen Leben. Mit dem factory-pattern. Noch besser, wenn Sie Namen für Ihre Fabrik das gleiche wie Ihre generischen Typ.
Bitte Stimmen Sie für die feature-request! Vorschlag: die Konstruktor-argument Typ-Inferenz
InformationsquelleAutor theburningmonk | 2010-08-25
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nicht. Wenn Sie
dann könnten wir identifizieren alle Typen namens Foo in Umfang unabhängig von generischen stelligkeit, und dann tun, überlast-Auflösung auf jedem mit einer modifizierten Methode Typ-Inferenz-Algorithmus. Wir würden dann zum erstellen eines 'betterness' - Algorithmus, der bestimmt, welche der beiden Konstruktoren anwendbar in zwei Typen, die haben den gleichen Namen, aber verschiedene generische stelligkeit ist die bessere Konstruktor. Um die Abwärtskompatibilität ein Tor auf einem nicht-generischen Typ, muss immer gewinnen.
Ja. Auch wenn der nutzen der Funktion überwiegt die Kosten, die erheblich sind-das ist nicht ausreichend, um eine Funktion implementiert. Nicht nur die Funktion haben ein Netto-Gewinn, es muss sich um eine großen Netto-Gewinn im Vergleich zu allen anderen möglichen Funktionen, könnten wir investieren. Es hat auch besser zu sein als die Zeit und Mühe auf die Fehlerbehebung, performance-Arbeit, und andere mögliche Bereiche, die wir stellen könnten, die Anstrengung. Und im Idealfall muss ich passen gut auf, was das "Thema" ist der release.
Darüber, wie man richtig beachten, können Sie die Vorteile dieser Eigenschaft, ohne die Funktion selbst, indem Sie mit einem factory-pattern. Die Existenz von einfachen workarounds, macht es weniger wahrscheinlich, dass ein feature jemals implementiert werden.
Diese Funktion wurde auf die Liste der möglichen Funktionen für eine lange Zeit jetzt. Es war noch nie annähernd hoch genug auf der Liste tatsächlich umgesetzt.
UPDATE März 2015
Die vorgeschlagene feature gemacht, es nah genug an der Spitze der Liste für C# 6 spezifiziert und konzipiert, wurde dann aber geschnitten.
Oh Gott Nein, der C# - compiler nicht alle möglichen Schlüsse ziehen. Zum Beispiel
class B<T> { public virtual void M<U>() where U : T {} } class D : B<int> { public override void M<U>() {} } ... (new D()).M();
- Sie und ich können unsere geistige Inferenz zu wissen, die verdammt sicher, dass das nur möglich ist, argument Typ ist int, aber der C# - compiler findet, der trick. Ich könnte die Liste der Beispiele, den ganzen Tag; unser Typ-Inferenz ist ziemlich schwach im Vergleich zu F#.Oder
short M<T>(out T y){...} ... var x = M(out x);
Sie und ich kann Grund, dass das nur möglich Rückgabetyp ist kurz, und daher x muss kurz sein, und daher T muss kurz sein. Aber der C# - compiler fällt über sofort wenn es beliebiger - Zyklus in einer implizit typisierten lokalen.Oder
void M<T>(T t1, T t2){} ... M(new Giraffe(), new Turtle());
Sie und ich kann Grund, dass der Schriftsteller sich der code vermutlich beabsichtigt T zu Tier, aber der C# - compiler keinen Grund, "Giraffe und Schildkröte teilen, eine gemeinsame Basis zu geben Tier, deshalb es ist der beste Kandidat für T".Sprache, die Konsistenz ist eine Priorität, aber es ist eine niedrige Priorität im Vergleich zu eher pragmatisch Bedenken. Und ich versichere Ihnen, wir haben eine Liste buchstäblich länger als Ihr arm von Funktionen, die nehmen einem Satz zu beschreiben; und hätten wir zwanzig mal das aktuelle budget hätten wir aber nicht umsetzen wollen, alles, was auf dieser Liste! Sie würde nicht wollen, verwenden Sie eine Sprache, wo jede mögliche Funktion, die Hinzugefügt werden könnten, wurde Hinzugefügt, glauben Sie mir. Wir wählen Sie, wie verbringen unsere geringem Aufwand äußerst sorgfältig, um die maximale Wertschöpfung für den Kunden.
InformationsquelleAutor Eric Lippert
können Sie, gibt es keine Notwendigkeit zu sagen, den Konstruktor ', was T' wieder, zu sehen, wie Sie bereits getan haben, die in der Klasse Unabhängigkeitserklärung.
auch Ihre Fabrik ist falsch, Sie müssen
public class MyTypeFactory<T>
nicht nurpublic class MyTypeFactory
- es sei denn, Sie deklarieren das Werk in derMyType
KlasseEdit für update:
Gut, ist 42 eine long, eine short, int, oder etwas anderes?
Lassen Sie uns sagen, Sie haben die folgenden
Dann hast du das
Würden Sie erwarten
foo
verwendet werden, oderbase
? Wir müssen, sagen Sie dem compiler, was zu verwenden anstelle vonT
Wenn Sie wirklich wollten, um auf Art
base
Daher die
Siehe mein edit, wenn das Werk innerhalb der MyType-Klasse es weiß, was T ist, aber wenn es nicht, müssen Sie T
Der compiler kann nicht folgern, der Typ da konnte mir mehrere Konstruktoren. Ergänzung zu deinem Beispiel, wie würde der compiler wissen, welcher Konstruktor aufgerufen werden soll, wenn
MyType(double)
vorhanden ist?aber in der Create-Methode kann der compiler einfach folgern, dass T int
Der Teil deiner Antwort bin ich uneins mit ist <Zitat>Ihr Werk ist falsch, Sie müssen
public class MyTypeFactory<T>
nicht nurpublic class MyTypeFactory
- es sei denn, Sie deklarieren das Werk in derMyType
Klasse</Zitat> Eigentlich das richtige istMyTypeFactory.Create<T>
wie die Frage jetzt ist, und nichtMyTypeFactory<T>.Create
was Sie sagten, war notwendig. MitMyTypeFactory<T>.Create
würde verhindern, dass Typ-Inferenz, da der generische parameter erscheinen vor den member-Referenz-operator.
kann nicht gefolgert werden, der auf eine Methode.InformationsquelleAutor PostMan
Der Hauptgrund generischen Typ-Inferenz, kann nicht auf Konstruktoren, wie Sie wollen, ist, weil die Klasse "MyType" gar nicht existieren, wenn alles, was Sie schon erklärt ist "MyType<T>". Denken Sie daran, es ist legal, beides zu haben:
und
Beides wäre legal. Wie würden Sie eindeutig machen Ihre syntax, wenn Sie in der Tat erklären beide, und beide von Ihnen erklärt, ein Konflikt Konstruktor.
InformationsquelleAutor Kirk Woll
Konstruktor muss den gleichen generischen Spezifikation wie die Klasse selbst. Sonst wäre es unmöglich zu wissen, ob die
int
in deinem Beispiel würde sich auf die Klasse oder den Konstruktor.Wäre das Klasse
MyType<T>
mit KonstruktorMyType(int)
oder KlasseMyType
mit KonstruktorMyType<T>(T)
?Wäre es nicht unmöglich zu wissen, in den meisten Fällen. In den Fällen, wo es konnte nicht eindeutig bestimmt ist, die beabsichtigt war, dann könnten wir dir eine Fehlermeldung geben. Dies ist die gleiche wie bei jeder anderen überlast Auflösung problem; wenn nicht genügend Informationen versorgt wird, dann haben wir einfach einen Fehler.
InformationsquelleAutor Albin Sunnanbo
Obwohl diese bereits beantwortet wurde viele Male zuvor, ich fühle, muss ich eine Sache klarstellen: C# unterstützt generischen Typ-Inferenz, die auf Konstruktoren. Das problem ist, dass es keinen support weder das hinzufügen generischer Parameter für Konstruktoren noch Typ generischen Typ-Inferenz. Wollen infer generic type Arguments der Typ selbst ist im Grunde das gleiche, als seien
Foo.Bar(0)
zu entnehmen, zuFoo<int>.Bar(0)
.InformationsquelleAutor IllidanS4