2016-08-22 64 views
6
static IEnumerable<U> DoSomething<T, U>(IEnumerable<T> a) 
    where T : U 
{ 
    // Works, compiler can compile-time statically cast 
    // T as U. 
    T testA = default(T); 
    U testB = testA; 

    // And the following works, though: 
    IEnumerable<string> test2A = null; 
    IEnumerable<object> test2B = test2A; 

    // Doesn’t work. Compiler cannot compile-time statically 
    // cast IEnumerable<T> to IEnumerable<U> even though it is 
    // out and T is U. 
    return a; 
} 

我有代碼在哪裏能夠執行這種類型的隱式轉換將節省我寫了很多樣板接口實現代碼。 這似乎是協方差本應幫助的事情。 但我總是得到這個錯誤在return a;線之上:爲什麼協變隱式轉換忽略通用約束?

錯誤CS0266:無法鍵入「System.Collections.Generic.IEnumerable <牛逼>」隱式轉換爲「System.Collections.Generic.IEnumerable <ü> 」。一個顯式轉換存在(是否缺少強制轉換?)

這是爲什麼這樣,是有辦法解決這個沒有做這樣的事情return from o in a select o;

回答

6

當我最小的攝製亂搞和讀取類似,但無關,問題about interface casting,我意識到,下面編譯:

static IEnumerable<U> DoSomethingElse<T, U>(IEnumerable<T> a) 
    where T : class, U 
{ 
    // Works! Ridik! 
    return a; 
} 

而且還下列失敗,出現相同的錯誤消息:

static void Blah() 
{ 
    // Fails for I bet the same reason that DoSomething{T, U} fails: 
    IEnumerable<int> a = null; 
    IEnumerable<object> b = a; 
} 

錯誤CS0266:無法隱式轉換類型 'System.Collections.Generic.IEnumerable <INT>' 到「System.Collections.Generic .IEnumeume <object>'。一個顯式轉換存在(是否缺少強制轉換?)

因此,這似乎與.NET如何限制某些類型的任務的引用類型,因爲拳擊在這些情況下,要麼是錯誤的東西(例如,你可能會假定引用類型,並且實際上正在處理一個值類型的副本),或者很難/不可能在運行時實現(給定一個IEnumerable<int>,你必須實現一個包裝適配類,OK,這聽起來像是某種東西。 net不能/不應該在運行時爲你做)。我認爲它是.net允許指針式多態的情況,它本質上與價值類型的概念不相容。

因此,對於我的情況,我不需要在我的API中支持值類型,並且添加約束使得所有內容都變得神奇!