2015-10-04 41 views
4

這可能有一個問題,但我沒有能夠拿出搜索條件來找到答案..IEnumerable中不能使用泛型類型的約束?

我可能在這裏丟失了一些明顯的東西,但爲什麼我不允許請執行以下操作,這會給出錯誤:

"Argument 1: cannot convert from System.Collections.Generic.IEnumerable<TType> to System.Collections.Generic.IEnumerable< Test.A> "

同時撥打DoSomething的電話?

public interface A 
{ 
    void Foo(); 
} 

public class B : A 
{ 
    public void Foo() 
    { 
    } 
} 

class Test<TType> where TType : A 
{ 
    public Test(IEnumerable<TType> testTypes) 
    { 
     DoSomething(testTypes); 
    } 

    void DoSomething(IEnumerable<A> someAs) 
    { 
    } 
} 

雖然它是的,當然,OK做到這一點:

class Test 
{ 
    public Test(IEnumerable<B> testTypes) 
    { 
     DoSomething(testTypes); 
    } 

    void DoSomething(IEnumerable<A> someAs) 
    { 
    } 
} 
+0

差異。如果'TTypes'是'struct',那麼'IEnumerable '不能被轉換成'IEnumerable '。如果你爲'TType'增加額外的'class'約束,那麼cast將被允許。 – PetSerAl

+0

謝謝 - 這是有道理的。對我來說代碼不是一個很大的問題,我只是很好奇,當我試圖做到這一點,並得到了錯誤。編輯:看到你編輯你的迴應,建議在where子句中使用class - 謝謝! – Matt

回答

5

方差僅適用於引用類型。在你的代碼TType也可以是一個值類型。如果添加class約束,該代碼將編譯

class Test<TType> where TType : class, A 
{ 
    public Test(IEnumerable<TType> testTypes) 
    { 
     DoSomething(testTypes); 
    } 

    void DoSomething(IEnumerable<A> someAs) 
    { 
    } 
} 

你可以找到一個詳細的解釋僅作參考類型支持here

+0

謝謝 - 非常有意義,我學到了一些有用的東西。 – Matt

+1

而且方差僅適用於引用類型,因爲值類型(結構)不能從另一類型繼承,因此可能無法真正應用方差。 –

+1

@PeterRitchie值類型可以實現接口,所以方差可以應用。但是將值類型轉換爲接口會導致裝箱,這會將表示更改爲引用。 –