Warum nicht C# - Unterstützung bedeutete generischen Typen, die Klasse Konstruktoren?

StackOverflow https://stackoverflow.com/questions/45604

  •  09-06-2019
  •  | 
  •  

Frage

C# erfordert nicht die Angabe einer generischen Typ-parameter, wenn der compiler ableiten können, zum Beispiel:

List<int> myInts = new List<int> {0,1,1,
    2,3,5,8,13,21,34,55,89,144,233,377,
    610,987,1597,2584,4181,6765};

//this statement is clunky
List<string> myStrings = myInts.
    Select<int,string>( i => i.ToString() ).
    ToList<string>();

//the type is inferred from the lambda expression
//the compiler knows that it's taking an int and 
//returning a string
List<string> myStrings = myInts.
    Select( i => i.ToString() ).
    ToList();

Dies ist nötig, um anonyme Typen, wo Sie nicht wissen, was die parameter " Typ " wäre (in intellisense zeigt es sich als 'a), weil es der compiler.

Klasse-level-Typ-Parameter nicht lassen Sie dies tun:

//sample generic class
public class GenericDemo<T> 
{
    public GenericDemo ( T value ) 
    {
        GenericTypedProperty = value;
    }

    public T GenericTypedProperty {get; set;}
}

//why can't I do:
int anIntValue = 4181;
var item = new GenericDemo( anIntValue ); //type inference fails

//however I can create a wrapper like this:
public static GenericDemo<T> Create<T> ( T value )
{
    return new GenericDemo<T> ( value );
}

//then this works - type inference on the method compiles
var item = Create( anIntValue );

Warum nicht C# unterstützen diese Klasse generischen Typ-Inferenz?

War es hilfreich?

Lösung

Tatsächlich, Ihre Frage ist nicht schlecht.Ich habe liebäugelt mit einer generische Programmierung Sprache für die letzten paar Jahre, und obwohl ich noch nie herum, um tatsächlich entwickeln (und wahrscheinlich auch nie wird), ich habe viel darüber nachgedacht, generische Typ-Inferenz und einer meiner top-Prioritäten schon immer erlauben die Konstruktion von Klassen, ohne Angabe der generische Typ.

C# fehlt einfach die Regeln, um dies zu ermöglichen.Ich denke, die Entwickler sahen nie die neccesity, um diese aufzunehmen.Eigentlich ist der folgende code wäre sehr nahe an Ihrem Vorschlag und lösen die problem.Alle C# muss eine zusätzliche syntax-Unterstützung.

class Foo<T> {
    public Foo(T x) { … }
}

// Notice: non-generic class overload. Possible in C#!
class Foo {
    public static Foo<T> ctor<T>(T x) { return new Foo<T>(x); }
}

var x = Foo.ctor(42);

Da dieser code tatsächlich funktioniert, haben wir gezeigt, dass das problem ist nicht der Semantik, sondern einfach eine fehlende Unterstützung.Ich denke, ich muss zurück zu nehmen meine früheren posting.;-)

Andere Tipps

Warum nicht C# unterstützen diese Klasse generischen Typ-Inferenz?

Denn Sie sind in der Regel mehrdeutig.Durch Kontrast, Typ-Inferenz ist trivial für Funktionsaufrufe (wenn alle Typen werden in den Argumenten).Aber im Fall der Konstruktor ruft (verherrlicht Funktionen, zum Wohle der Diskussion), der compiler hat, um mehrere Ebenen zur gleichen Zeit.Eine Ebene der Klasse und der andere ist der Konstruktor Argumente Ebene.Ich glaube, die Lösung dieses ist algorithmisch nicht-trivial.Intuitiv würde ich sagen, es ist sogar NP-vollständig.

Um zu veranschaulichen, ein Extremfall, bei dem die Auflösung ist unmöglich, stellen Sie sich die folgende Klasse und mir sagen, was der compiler tun sollten:

class Foo<T> {
    public Foo<U>(U x) { }
}

var x = new Foo(1);

Dank Konrad, das ist eine gute Antwort (+1), aber nur zu erweitern es.

Wir behaupten, dass C# einen expliziten Konstruktor-Funktion:

//your example
var x = new Foo( 1 );

//becomes
var x = Foo.ctor( 1 );

//your problem is valid because this would be
var x = Foo<T>.ctor<int>( 1 );
//and T can't be inferred

Du hast ganz Recht, dass der erste Konstruktor kann nicht abgeleitet werden.

Jetzt gehen wir zurück in die Klasse

class Foo<T> 
{
    //<T> can't mean anything else in this context
    public Foo(T x) { }
}

//this would now throw an exception unless the
//typeparam matches the parameter
var x = Foo<int>.ctor( 1 );

//so why wouldn't this work?
var x = Foo.ctor( 1 );

Natürlich, wenn ich den Konstruktor zurück in der (mit seinen alternate-Art) wir haben eine zweideutige call - genau wie bei einer normalen überladen von Methoden konnte nicht aufgelöst werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top