2012-02-20 63 views
13

UPDATE:下面的代碼纔有意義,在C#4.0(Visual Studio 2010中)協方差/逆變:如何讓下面的代碼編譯

好像我有協的一些誤解/逆變事。任何人都可以告訴我爲什麼下面的代碼不能編譯?

public class TestOne<TBase> 
{ 
    public IEnumerable<TBase> Method<TDerived>(IEnumerable<TDerived> values) 
     where TDerived: TBase 
    { 
     return values; 
    } 
} 

,而這一個編譯:(!!!)

public interface IBase 
{ 
} 
public interface IDerived: IBase 
{ 
} 
public class TestTwo 
{ 
    public IEnumerable<IBase> Method(IEnumerable<IDerived> values) 
    { 
     return values; 
    } 
} 

回答

13

協方差僅適用於引用類型(類型參數),所以你必須添加一個類約束:

public IEnumerable<TBase> Method<TDerived>(IEnumerable<TDerived> values) 
    where TDerived : class, TBase 
{ 
    return values; 
} 

這會阻止您嘗試將IEnumerable<int>轉換爲IEnumerable<object>,這是無效的。

+0

@Adam:我相信你是錯的,IEnumerable的''不'IEnumerable的'默認所以它不會編譯甚至在'3.5' – sll 2012-02-20 15:39:04

+1

@AdamMihalcin:沒有,那個代碼*不會*在.NET 4之前編譯過。我剛剛嘗試過驗證它。如果沒有泛型不變性,從IEnumerable 到IEnumerable 的轉換簡直是無效的。 – 2012-02-20 15:39:42

+0

TSuper的良好通話,只是修復了 – 2012-02-20 15:42:34

1

我想不出你實際需要的任何情況TDerived。使用TBase充足:

public class TestOne<TBase> 
{ 
    public IEnumerable<TBase> Method(IEnumerable<TBase> values) 
    { 
     return values; 
    } 
} 

畢竟,你有沒有有關TDerived從事實上除了它是一個TBase ...

+2

不幸的是,這不是我爲了複雜性而編造的,這是一個真實的情況,我最終得到了在我的代碼 – 2012-02-20 15:45:57

+1

@bonomo:這很有趣,我很樂意看到一個更詳細的示例供將來參考。 :-) – linepogl 2012-02-20 15:49:04

0

無論是最初編爲我。這兩個都從Super(T/I)到Base(T/I)的隱式演員都失敗了。然而,當我添加一個明確的案例時,兩者都被編譯。

public IEnumerable<TBase> Method<TSuper>(IEnumerable<TSuper> values) 
    where TSuper: TBase 
    { 
     return (IEnumerable<TBase>) values; 
    }