我有一个接口IPerson
和两个实现它的类Adventurer
和Worker
。我目前为冒险家和工人分别有ObservableCollection
个。我有一个方法,我希望能够将ObservableCollection<Adventurer>
和ObservableCollection<Worker>
作为参数传递给我,到目前为止我还没有运气。该方法仅使用IPerson
中实现的属性,如果我将其声明为:
public void MyMethod(ObservableCollection<IPerson> collection)
...方法本身内部没有错误。但是,当我尝试传入ObservableCollection<Adventurer>
时,我收到了2个错误:
无法从'System.Collections.ObjectModel.ObservableCollection'转换为'System.Collections.ObjectModel.ObservableCollection'。
和
'AoW.MyMethod(System.Collections.ObjectModel.ObservableCollection)'的最佳重载方法匹配有一些无效的参数。
我可以将ObservableCollection
两个传递给同一个方法吗?如果是这样,我应该怎么做呢?任何建议都将不胜感激。
答案 0 :(得分:3)
.NET中的类不支持covariance and contravariance。只有接口才有。想象一下这种情况:
class Adventurer : IPerson { }
class NPC : IPerson { }
public void MyMethod(ObservableCollection<IPerson> collection)
{
collection.Add(new NPC());
}
var collectionOfAdventurers = new ObservableCollection<Adventurer>();
MyMethod(collectionOfAdventurers);
这显然会引发一些错误,因为传入的类型是Adventurer
集合,但该方法添加了NPC
,但这在编译时无法验证。因此,编译器要求传入的类型必须与签名中的类型完全匹配,而不是允许这样的不安全行为,如果您尝试传入其他任何内容,则会出错。
我建议将MyMethod
更改为:
public void MyMethod(IEnumerable<IPerson> enumerable)
或者
public void MyMethod(INotifyCollectionChanged collection)
具体取决于您需要访问的成员。
您可能还想考虑一种通用方法:
public void MyMethod<T>(ObservableCollection<T> collection) where T : IPerson
答案 1 :(得分:0)
你不能这样做,因为
ObservableCollection<IPerson>
时 本身是另一种类型(例如,你可以把冒险家或工人放在其中,你不能在冒险家或工人的集合中做到这一点)
解决方案可能是在您的方法中允许IEnumerable的IPerson,然后使用以下方法调用它:
ObservableCollection<Worker> col = ...
MyMethod(col.Cast<IPerson>());