2013-05-27 17 views
5

不要認爲標題可以解釋我在說什麼,並且解釋有點困難,所以我會讓代碼進行交談。你可以複製+粘貼到LINQPad並作爲C#程序運行它,或者在Visual Studio中作爲常規C#項目進行必要的調整(例如:將調用轉換爲Dump()到Console.Writeline()等) -即使它實現了所需的接口,通用對象仍然需要投射

請注意,如果您取消註釋doStuff方法中的行,它將不會編譯。

我的問題是,爲什麼當generic2已經實現Iab<TA,TB>時我需要投射?這是一些協變的東西嗎?我仍然在.NET 3.5上。

void Main() 
{ 
    doStuff<a,b>(); 
} 

public void doStuff<TA, TB>() 
where TA : class, Ia, new() 
where TB : class, Ib, new() 
{ 
    Iab<TA, TB> x = null; 

    x = new generic1<TA, TB>(); 
    x.Go().Dump(); 

    //x = new generic2<TA>(); // <-Cannot implicitly convert type 'UserQuery.generic2<TA>' to 'UserQuery.Iab<TA,TB>'. An explicit conversion exists (are you missing a cast?) 
    x = (Iab<TA, TB>) new generic2<TA>(); 
    x.Go().Dump(); 
} 

public interface Ia 
{} 

public interface Ib 
{} 

public class a : Ia 
{} 

public class b : Ib 
{} 

public interface Iab<TA,TB> 
where TA : class, Ia, new() 
where TB : class, Ib, new() 
{ 
    string Go(); 
} 

public class generic1<TA, TB> : Iab<TA,TB> 
where TA : class, Ia, new() 
where TB : class, Ib, new() 
{ 
    public string Go() 
    { 
     return "generic Base called"; 
    } 
} 

public class generic2<TA> : Iab<TA,b> 
where TA : class, Ia, new() 
{ 
public string Go() 
    { 
     return "generic Sub called"; 
    } 
} 

回答

4

我相信這是因爲你總是會得到這個錯誤時,類型(在這種情況下,TS)中的一個或多個在編譯時已知的。

編譯器不能保證doStuff()將被調用兼容類型,所以它強制你投。

明白爲什麼編譯器不能做到這一點,嘗試調用doStuff()如下:

public class X: b {} 

... 

doStuff<a, X>(); // Compiles ok but: 

未處理的異常:System.InvalidCastException:無法投類型的對象GENERIC2 1[Demo.Program+X]' to type 'Iab 2演示。項目+ X,Demo.Program + Y]」。

因此,您可以使用會使其崩潰的類型來調用它;編譯器不會默默地讓你這樣做。

+0

啊,是的,當然。錯過了那一個:)謝謝! –

相關問題