将泛型类型分配给属性

时间:2012-09-03 09:24:35

标签: c# generics

我希望我的对象能够引用他们所居住的集合。

我有一个派生类派生自ObservableCollection<>

public class MyObservableCollection<T> : ObservableCollection<T> where T: class, IMyItem

public interface IMyItem
{
   MyObservableCollection<IMyItem> Owner;
}

在其中,我已覆盖Insert( )Remove( ),以便它可以将自己分配给IMyItem上的属性,但我不允许因为

Cannot implicitly convert type 'MyObservableCollection<T>' to
'MyObservableCollection<IMyItem>'

如何解决这个问题?
可以/应该以完全不同的方式解决问题吗?

插入代码:

    protected override void InsertItem(int index, T item)
    {
        base.InsertItem(index, item);
        item.Owner = this;
    }

2 个答案:

答案 0 :(得分:1)

如果您定义了这样的界面,它应该可以工作:

public interface IMyItem<T> where T : class, IMyItem<T>
{
    MyObservableCollection<T> Owner { get; set; }
}

public class MyItem : IMyItem<MyItem>
{
    public MyObservableCollection<MyItem> Owner { get; set; }
}

public class MyObservableCollection<T> : ObservableCollection<T> where T : class, IMyItem<T>
{
    protected override void InsertItem ( int index, T item )
    {
        base.InsertItem ( index, item );
        item.Owner = this;
    }
}

用法:

public class MyClass
{
    public static void Main ()
    {
        MyObservableCollection<MyItem> list = new MyObservableCollection<MyItem> ();
        list.Add ( new MyItem () );
    }
}

答案 1 :(得分:0)

假设您有实现接口的Item类:

class Item : IMyItem
{
    public MyObservableCollection<IMyItem> Owner;
}

现在,您正在创建一个新集合:

var myCollection = new MyObservableCollection<Item>();
myCollection.Insert(new Item());

现在,在您的Insert()方法中,您正在执行此任务:

newItem.Owner = this;

但您的newItem.Owner类型为MyObservableCollection<IMyItem>,而this属于更具体的类型MyObservableCollection<Item>。你遇到的是通用covariance/contravariance的问题。 Item可能会继承IMyItem,但List<Item>不会继承List<IMyItem>

Stephan Bauer的回答为您提供了一种解决方法,让IMyItem接口具有对自身的通用引用,从而跳过整个协方差问题。另一个想法是使用IEnumerable<T>而不是ObservableCollection<T>,因为IEnumerable被定义为<out T>,这意味着它支持继承期间的协方差。