C# 关于泛型和继承(请原谅我的坏标题)

C# 关于泛型和继承(请原谅我的坏标题),c#,generics,covariance,C#,Generics,Covariance,因为我不知道我的问题叫什么,我不能保证,最近或根本没有人问过同样的问题 然而,我确实注意到,有相当多的线程具有类似的标题,但它们似乎与我的问题无关 我有一个自定义列表类,它实现了泛型 class MyList<T> { public void add(T item) // adds an item to the list { /* code */ } public void add(MyList<T> list) // attaches an ex

因为我不知道我的问题叫什么,我不能保证,最近或根本没有人问过同样的问题

然而,我确实注意到,有相当多的线程具有类似的标题,但它们似乎与我的问题无关

我有一个自定义列表类,它实现了泛型

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 */ }
}

现在,相关代码出现了:

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?
MyList水果列表=新建MyList();
//填写结果表
水果列表。添加(新苹果());//当然可以
水果列表。添加(新香蕉());//当然,效果也不错
MyList appleList=新的MyList();
//填写申请表
水果列表。添加(苹果列表);//不起作用。为什么?
尽管appleList是(苹果的)MyList,Apple是水果,但VisualStudio在询问(水果的)MyList时不接受(苹果的)MyList作为参数

然而,如果我像这样宣布名单:

MyList<object> fruitList = new MyList<object>();
MyList水果列表=新建MyList();
然后一切又恢复了。我到底做错了什么

如果您能给出答案,我们将不胜感激,并感谢您花时间阅读,即使您没有回答。

您正在尝试使用。
.Net只支持接口上的通用差异,因此这不起作用

此外,协方差仅对不可变类型有意义。
如果可以将
MyList
转换为
MyList
,则可以将
橙色
添加到列表中,从而违反类型安全

相反,您可以将该方法设置为泛型:

public void Add<U>(IList<U> list) where U : T
public void Add(IList列表),其中U:T

我认为IMyList接口的设计应该是:

public interface IMyList<T> : IEnumerable<T>
{
    void Add(T item);
    void AddRange(IEnumerable<T> itemList);
}
公共接口IMyList:IEnumerable
{
无效添加(T项);
void AddRange(IEnumerable itemList);
}
一切正常。为什么?因为在.NET 4.0 IEnumerable接口中,其类型参数T是协变的,所以定义如下:

public interface IEnumerable<out T> : IEnumerable
公共接口IEnumerable:IEnumerable
IMyList接口(列表装饰器)的简单实现:

public类MyList:IMyList
{
私有只读列表_List=new List();
#IMyList的区域实现
公共作废新增(T项)
{
WriteLine(“添加项:{0}”,item);
_列表。添加(项目);
}
public void AddRange(IEnumerable itemList)
{
Console.WriteLine(“添加项目!”);
_list.AddRange(itemList);
}
#端区
#IEnumerable的区域实现
公共IEnumerator GetEnumerator()
{
返回_list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
返回GetEnumerator();
}
#端区
}

FYI,关于这一点的主要关键词是协方差、反方差和不变性。是的,当您不知道它时,很难找到它。您应该实现
IList
。在.Net中,公共成员名称应该是大写的。
public interface IMyList<T> : IEnumerable<T>
{
    void Add(T item);
    void AddRange(IEnumerable<T> itemList);
}
public interface IEnumerable<out T> : IEnumerable
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
}