2016-11-24 7 views

Antwort

1
IExample<IFoo, IBar> ex_huh = ex; //How can I do this? 

Sie können nicht, weil es Typsicherheit brechen würde. Und das liegt daran, dass Sie versuchen, den Parametertyp Ihrer Methode (diesen Parameter auf Foo(B b)) allgemeiner zu machen, und das ist nicht sicher.

Um es einfacher zu verstehen, warum das ein Problem ist, lassen Sie uns Ihr Beispiel lässt sich auf etwas Gleichwertiges (soweit diese Methode Parameter geht):

function DoSomethingWithFoo(Foo foo) { ... } 
// The following line won't compile, but let's pretend it does and see what happens 
Action<IFoo> doSomethingWithIFoo = DoSomethingWithFoo; 
doSomethingWithIFoo(new OtherFoo()); 

wo OtherFoo eine andere Klasse, die IFoo implementiert, aber stammt nicht aus der Foo Klasse.

Whoops! Sie rufen DoSomethingWithFoo, die eine Instanz von Foo erwartet, aber eine OtherFoo stattdessen übergeben! Verrückte Hijinks folgen.

Das ist im Wesentlichen, was Sie in Ihrem Beispiel zu tun versuchen. Sie versuchen, eine Klasse mit einer Methode zu verwenden, die einen Parameter des Typs Foo erwartet, und dies auf etwas zu setzen, mit dem Sie stattdessen IFoo übergeben können.

(Und das ist, warum die Compiler lassen Sie nicht IExample ‚s B Typparameter als out B, erklären, welche, was es Ihnen ein IExample<..., Foo> werfen zu einem IExample<..., IFoo> sein müßte zu lassen. Der Compiler sieht, dass der B Typen Parameter wird der Typ eines Verfahrensparameters verwendet, und deshalb wäre es kovarianter machen Typsicherheit brechen)


was, wie zu erreichen, was Sie suchen. das wird abhängen. Ihr konkretes Beispiel zu wollen tun

IExample<...figure out how to declare this...> = ...any IExample<A, B>...; 
ex_huh2.Foo(new Bar()); 

wird nicht im Allgemeinen arbeiten, denn das „... jede IExample<A, B> ...“ gut könnte ein IExample<..., OtherBar> sein, und dann kann man nicht geben sie ein new Bar(). Sie müssen herausfinden, wie Sie diesen Konflikt lösen möchten.

Vielleicht wirklich wollen Sie in einem new Bar() passieren, wobei in diesem Fall vielleicht Sie, dass innerhalb einer Methode machen wollen, die nur unter IExample s mit Bar als ihren zweiten Typ-Parameter beschränkt ist:

public void AddABar<TFoo>(IExample<TFoo, Bar> example) 
{ 
    example.Foo(new Bar()); 
} 

Or vielleicht möchten Sie eine neue Instanz zu schaffen, die unabhängig von der zweiten Art Parameter ist:

public void AddAThing<TFoo, TBar>(IExample<TFoo, TBar> example) 
    where TBar : new() 
{ 
    example.Foo(new TBar()); 
} 

Oder vielleicht möchten Sie IExample<A, B> stammen von einem nicht-generic machen IExample, das eine nicht-generische Foo(IBar b) deklariert, implementieren Sie diese nicht-generische Methode auf Ihre Example Klasse, und machen Sie eine Typumwandlung zu B innerhalb dieser Methode - das Risiko einzugehen, wenn Sie den falschen Typ in dieser Methode zur Laufzeit übergeben Holen Sie sich eine InvalidCastException.

Es kommt wirklich alles darauf an, wie Sie diesen Konflikt lösen von "Ich möchte dies zu etwas, ich kann ein new Bar() zu übergeben", wenn in der Tat jede gegebene Implementierung von IExample<A, B> nicht unbedingt in der Lage sein wird einen new Bar() als Methodenparameter zu akzeptieren.