2012-10-01 81 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和你的博客)。不知怎的,因为在那个特定的情况下,它是一个正确类型的集合,我想不出有人使用它的方式是错误的。我需要回到制图板,以防止有人以错误的方式使用它。 –

相关问题