2011-02-16 184 views
1

我创建了一个类,MonitoredCollection<T>时不再工作,基本上封装/模拟名单,但可以让我开枪某些呼叫事件。接口使用自定义集合类

然而现在,徘徊无论有一个参数,需要一个MonitoredCollection,其中T是一个接口,我不能再通过一个MonitoredCollection<T>其中T是实现该接口的类,如我可以用List

我一直以为接口是一个语言“功能”,因此,我并不需要实现更多的东西来支持这一点,所以你有什么我错过了?

编辑:对不起,我在这个问题犯了一个错误,因为若昂正确地指出,名单在这种情况下从来没有做过这样的问题是因为它代表的是没有!

+1

你是如何定义集合类的约束?我们可以看到一些代码吗? – 2011-02-16 20:27:51

+3

正如旁注;检查出ObservableCollection ,因为它可能提供您所需的行为已经 – 2011-02-16 20:28:52

+2

正如评论,这个答案由Eric Lippert吹了我的脑海,可能会帮助你:http://stackoverflow.com/questions/4923936/c-casting-a-generic - 元素类型向下 – 2011-02-16 20:46:30

回答

3

假设您有一个MonitoredCollection<SomeObject>实例,并且您想将其视为MonitoredCollection<ISomeInterface>实例,其中SomeObject事实上实际上实现了ISomeInterface。这对于从集合中检索项目不会产生任何问题,因为SomeObject类型的对象可以转换为接口类型ISomeInterface

但是,对于集合中用于修改集合的所有方法,例如为集合指定新值或向集合中插入新项目的操作,此类集合创建了一整套问题。我会假设你的MonitoredCollection<SomeObject>实例有一个方法,如Add(SomeObject obj),它会在集合中插入一个新的对象。演员之后,此方法的签名将为Add(ISomeInterface obj)。这似乎是有道理的,但不是所有的对象都是必需的SomeObject实例。

由于铸造对象将允许在收集原始对象不会允许操作,运行时不会允许这种转换。 C#4.0引入了协变和逆变来明确说明这种类型转换的有效性,你可以研究它们以解决这个问题。然而,你真的只会对你的集合的只读版本有运气(想想List<T>.AsReadOnly())。

1

不幸的是,你不能这样做,有一个列表无论是。编译器仍然无法转换类型。你需要使用一个通用的方法。见下面的代码:

class Test 
{ 
    void DoTest() 
    { 
     MonitoredList<IInterface> mlist1 = new MonitoredList<Inherited>(); //Error 
     MonitoredList<Inherited> mlist2 = new MonitoredList<Inherited>(); 
     DoSomething1(mlist2); //Error converting MonitoredList<Inherited> to MonitoredList<IInterface> 

     MonitoredList<IInterface> list1 = new MonitoredList<Inherited>(); //Error 
     MonitoredList<Inherited> list2 = new MonitoredList<Inherited>(); 
     DoSomething2(list2); //Error converting List<Inherited> to List<IInterface> 

     DoSomething3<Inherited>(mlist2); //Works fine 
     DoSomething3(mlist2); //<Inherited> is redundant 
    } 

    void DoSomething1(List<IInterface> list) 
    { } 

    void DoSomething2(MonitoredList<IInterface> list) 
    { } 

    //Generic method 
    void DoSomething3<T>(MonitoredList<T> list) where T : IInterface 
    { } 
} 

interface IInterface { } 

class Inherited : IInterface { } 

class MonitoredList<T> { }