为什么方法不能声明返回类型"List<IMyInterface>"并返回实现它的具体类



我有以下接口

public interface IMyInterface
{
    // Some method and property signatures
}

我有以下类实现上述接口

的类
public class MyClass : IMyInterface
{
    // Some methods and properties as declared by IMyInterface
}

然后,我在某些随机类中有此方法,我想返回实现IMyInterface的对象列表。在此特定的实现中,这些对象是MyClass的实例。

public List<IMyInterface> getItems(int id)
{
    return new List<MyClass>();
}

这将导致编译错误(在Visual Studio中也可以实时可见)

不能隐式转换类型 'System.Collections.generic.LIST&lt; myclass&gt;' 到 'system.collections.generic.list&lt; imyinterface&gt;'

我搜索了互联网,终于找到了这个线程C#接口和通用列表然后,我最终得到了以下方法

public List<IMyInterface> getItems(int id)
{
    return new List<MyClass>().Cast<IMyInterface>().ToList();
}

这会编译,但是对我来说,这似乎是一种处理它的奇怪方法。将混凝土类施放到界面。在线程c#接口和通用列表中,aeeeequitarum custos对接受答案的评论表明不必这样做。

我错过了什么还是这样做的方法?

,因为即使BaseParent的子类型,也不意味着List<Base>List<Parent>的子类型。IList<T>在其通用参数中是不变的,List<T>也是如此(C#不支持类方差,仅接口差异)。

在此处阅读有关协方差,违反和不变性的更多信息:http://blogs.msdn.com/b/csharpfaq/archive/2010/02/02/16/covariance-and-contravariance-and-contravariance-faq.aspx.aspx

如果List<T>是协变量的,您可以这样做:

List<Parent> list = new List<Base>();

如果您这样做会发生什么?

list.Add(new OtherBase());

这在编译时肯定是合法的,但会导致运行时错误。

这是因为 List<T>中的 T参数不是 variant 。但它在IEnumerable<out T>中:

out t

列举的对象类型。

此类型参数是协变量的。也就是说,您可以使用指定的类型或更派生的任何类型。

因此,如果您考虑更改getItems的签名:

public IEnumerable<IMyInterface> getItems(int id)
{
    return new List<MyClass>() as IEnumerable<IMyInterface>;
}

您可以找到有关协方差 contravariance 的更多信息。

考虑此示例:

public interface IAnimal
{
}
public class Cat : IAnimal
{
}
public class Dog : IAnimal
{
}

您等效的方法:

public List<IAnimal> getAnimals()
{
    return new List<Dog>();
}

// You just Dog'd a list of Cats
IEnumerable<Cat> cats = getAnimals();

最新更新