2010-04-19 286 views
6

考慮,我有以下3類/接口:鑄造泛型和泛型類型

class MyClass<T> { } 

interface IMyInterface { } 

class Derived : IMyInterface { } 

而且我希望能夠到MyClass<Derived>鑄造成MyClass<IMyInterface>,反之亦然:

MyClass<Derived> a = new MyClass<Derived>(); 
MyClass<IMyInterface> b = (MyClass<IMyInterface>)a; 

但我得到編譯器錯誤,如果我嘗試:

Cannot convert type 'MyClass<Derived>' to 'MyClass<IMyInterface>' 

我敢肯定有一個很好的重新不知爲什麼我不能這樣做,但我想不出一個。

至於爲什麼我想這樣做 - 我想象的場景是你最好想用MyClass<Derived>的實例工作,以避免大量討厭的演員,但是你需要將你的實例傳遞給接受MyClass<IMyInterface>的接口。

所以我的問題是雙重的:

  • 我爲什麼不能投這兩種類型?
  • 有什麼辦法保持與MyClass<Derived>實例一起工作的好處,同時仍然可以將其轉換爲MyClass<IMyInterface>

回答

5

這不起作用,因爲C#只支持接口和委託類型參數的協方差。如果你的類型參數只存在於輸出位置(即你只能從你的類返回它的實例,並且不接受它作爲參數),你可以創建這樣一個接口:

interface IClass<out T> { } 
class MyClass<T> : IClass<T> { } 

這將讓你做到這一點:

IClass<Derived> a = new MyClass<Derived>(); 
IClass<IMyInterface> b = a; 

老實說,就像你將要得到的一樣近,這需要C#4編譯器的工作。

3

你不能這樣做的原因一般是因爲大多數類不是簡單的空例子。他們有方法:

class MyClass<T> 
{ 
    static T _storage; 

    public void DoSomethingWith(T obj) 
    { 
     _storage = obj; 
    } 
} 

interface IMyInterface { } 

class Derived : IMyInterface { } 

MyClass<Derived> a = new MyClass<Derived>(); 

現在,a有接受Derived類型的靜態變量Derived並將其存儲的方法DoSomethingWith

MyClass<IMyInterface> b = (MyClass<IMyInterface>)a; 

如果被允許,b將現在似乎有一種方法DoSomethingWith接受任何實現IMyInterface,並隨後將在內部嘗試將其存儲在Derived類型的靜態變量,因爲它仍然是真的與a相同的對象。

所以現在你會有一個變量Derived存儲......誰知道什麼。