2012-10-01 121 views
2

我想知道爲什麼下面的通用方法不能編譯(C#4.0)。我和我的同事都無法弄清楚。爲什麼這種類型約束的泛型方法不能編譯?

編譯器抱怨this這是一個SelectableRowBase不能轉換爲TItem,這是SelectableRowBase派生的限制。如果我把所有東西都顯式轉換(這是我在源代碼控制中檢查的東西),但我想知道爲什麼編譯器在這裏抱怨。

這是一個編譯器錯誤?我錯過了什麼嗎?

public class SelectableRowBase 
{ 
    public void AddToSelectedListWhenIsSelectedChanges<TItem> 
      (ObservableCollection<TItem> selectedList) 

     where TItem : SelectableRowBase 
    { 
     // Causes error: 
     // The best overloaded method match for 
     //  'System.Collections.ObjectModel.Collection<TItem>.Add(TItem)' 
     //  has some invalid arguments 
     // Argument 1: cannot convert from SelectableRowBase' to 'TItem' 
     Action actionOnSelected =() => selectedList.Add(this); 
     Action actionOnDeselected =() => selectedList.Remove(this); 

     // Compiles and works fine 
     // only difference is the explicit cast 
     Action actionOnSelected =() => selectedList.Add((TItem)this); 
     Action actionOnDeselected =() => selectedList.Remove((TItem)this); 
    } 
} 

回答

4

這是完全合理的,它不工作。

您正試圖將基底類型的實例添加到潛在的派生的類型的集合中。

這就像試圖寫:

List<string> strings = new List<string>(); 
strings.Add(new object()); 

這將違反類型安全。

基本上,絕對不能保證thisTItem的實例。它可能是這就是爲什麼演員編譯 - 但它可能不會。該演員陣容是一個真的很糟糕的主意 - 它將類型安全性留給執行時間,這與泛型的目的相反。

+0

感謝喬恩,我知道這將涉及到類型安全(我讀了Eric Lippert和你的博客)。不知怎的,因爲在那個特定的情況下,它是一個正確類型的集合,我想不出有人使用它的方式是錯誤的。我需要回到製圖板,以防止有人以錯誤的方式使用它。 –

相關問題