由于我不知道如何调用我的问题,我无法保证,最近或根本没有人提出同样的问题。
我注意到,但是有很多线程都有类似的标题,但它们似乎与我的问题无关。
我有一个自定义列表类,它实现了泛型。
class MyList<T>
{
public void add(T item) // adds an item to the list
{ /* code */ }
public void add(MyList<T> list) // attaches an existing list to the end of the current one
{ /* code */ }
}
我也有课程:
class Apple : Fruit
和
class Banana : Fruit
现在,来自相关代码:
MyList<Fruit> fruitList = new MyList<Fruit>();
// fill fruitList
fruitList.add(new Apple()); // works, of course
fruitList.add(new Banana()); // works as well, of course
MyList<Apple> appleList = new MyList<Apple>();
// fill appleList
fruitList.add(appleList); // doesn't work. Why?
尽管appleList是MyList(Of Apple)而Apple是Fruit,但当MyList(Of Fruit)被问到时,VisualStudio不接受MyList(Of Apple)作为参数。
但是,如果我要声明这样的列表:
MyList<object> fruitList = new MyList<object>();
然后一切都恢复正常。究竟我做错了什么?
非常感谢答案,感谢您抽出时间阅读,即使没有回答。
答案 0 :(得分:8)
您正在尝试使用covariance .Net仅支持接口上的泛型差异,因此不起作用。
此外,协方差仅对不可变类型有意义
如果可以将MyList<Apple>
转换为MyList<Fruit>
,您就可以在列表中添加Orange
,违反了类型安全。
相反,您可以使方法通用:
public void Add<U>(IList<U> list) where U : T
答案 1 :(得分:3)
我认为IMyList接口的设计应该是:
public interface IMyList<T> : IEnumerable<T>
{
void Add(T item);
void AddRange(IEnumerable<T> itemList);
}
一切都按预期工作。为什么?仅仅因为在.NET 4.0中IEnumerable接口在它的类型参数T中是协变的,这就是定义的样子:
public interface IEnumerable<out T> : IEnumerable
IMyList接口的简单实现(List decorator):
public class MyList<T> : IMyList<T>
{
private readonly List<T> _list = new List<T>();
#region Implementation of IMyList<in T>
public void Add(T item)
{
Console.WriteLine("Adding an item: {0}", item);
_list.Add(item);
}
public void AddRange(IEnumerable<T> itemList)
{
Console.WriteLine("Adding items!");
_list.AddRange(itemList);
}
#endregion
#region Implementation of IEnumerable
public IEnumerator<T> GetEnumerator()
{
return _list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}