简体   繁体   English

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

[英]Why can't a method declare return type `List<IMyInterface>` and return a concrete class implementing it

I have the following interface 我有以下界面

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

I have the following class implementing the above interface 我有以下类实现上面的接口

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

Then I have this method in some random class, that I want to return a list of objects implementing IMyInterface . 然后我在一些随机类中有这个方法,我想返回一个实现IMyInterface的对象列表。 In this particular implementation these objects are instances of MyClass . 在这个特定的实现中,这些对象是MyClass实例。

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

This will result in a compile error (Visible in real time as well, in Visual Studio) 这将导致编译错误(在Visual Studio中也可实时显示)

Cannot implicitly convert type 'System.Collections.Generic.List<MyClass>' to 'System.Collections.Generic.List<IMyInterface>' 无法将类型'System.Collections.Generic.List <MyClass>'隐式转换为'System.Collections.Generic.List <IMyInterface>'

I've searched the internet and finally found this thread C# Interfaces and Generic Lists I then ended up with the following method 我搜索了互联网,最后找到了这个线程C#接口和通用列表 ,然后我最终得到了以下方法

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

This will compile, but to me it seem to be a really odd way to handle it; 这将编译,但对我来说,处理它似乎是一种非常奇怪的方式; Casting a concrete class to an Interface. 将具体类转换为接口。 In the thread C# Interfaces and Generic Lists Aequitarum Custos comment to the accepted answer indicate that this should not have to be done. 在线程C#接口和通用列表 Aequitarum Custos对接受的答案的评论表明不应该这样做。

Am I missing something or is this the way to do it? 我错过了什么或这是这样做的方式吗?

Because even though Base is a subtype of Parent , doesnt mean List<Base> is a subtype of List<Parent> . 因为即使BaseParent的子类型,也不意味着List<Base>List<Parent>的子类型。 IList<T> is invariant in its generic parameter, and so is List<T> (c# doesn't support class variance, only interface variance). IList<T>在其泛型参数中是不变的,因此List<T> (c#不支持类方差,只支持接口方差)。

Read more about covariance, contravariance and invariance here: http://blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx 阅读更多关于协方差,逆变和不变性的信息: http//blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx

If List<T> was covariant, and you were allowed to do this: 如果List<T>是协变的,那么你被允许这样做:

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

What would happen if you then did this? 如果你这样做会怎么样?

list.Add(new OtherBase());

This would certainly be legal at compile time, but cause a runtime error. 这在编译时肯定是合法的,但会导致运行时错误。

This is because T parameter in List<T> is not covariant . 这是因为List<T> T参数不是协变的 But it is in IEnumerable<out T> : 但它在IEnumerable<out T>

out T 出来

The type of objects to enumerate. 要枚举的对象的类型。

This type parameter is covariant. 此类型参数是协变的。 That is, you can use either the type you specified or any type that is more derived. 也就是说,您可以使用指定的类型或更多派生的类型。

So you can do this, if you'd consider to change signature of getItems : 如果您考虑更改getItems签名,那么您可以这样做:

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

You can find more information about covariance and contravariance here . 您可以在此处找到有关协方差逆变的更多信息。

Consider this example: 考虑这个例子:

public interface IAnimal
{
}

public class Cat : IAnimal
{
}

public class Dog : IAnimal
{
}

And you equivalent method: 而你等效的方法:

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


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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么我不能声明通用列表 <T> 作为接口方法的返回类型? - Why can't I declare generic List<T> as return type for interface method? 如何从具有泛型返回类型的方法返回具体类的实例 - How to return instance of concrete class from method with generic return type 实现定义基类属性的接口时,为什么类实现接口不能返回派生类类型对象? - When implementing an interface which define a base class property why can't the class implementing interface return a derived class type object? 在抽象类中返回具体类型 - Return concrete type in abstract class 方法声明的返回类型应该是接口还是具体类? - Should the return type of a method declaration be interface or concrete class? 返回IEnumerable <IMyInterface> 从清单 <MyInterfaceClass> - Return IEnumerable<IMyInterface> from List<MyInterfaceClass> 用具体类型覆盖抽象方法的返回类型 - Override abstract method return type with concrete type 如何模拟通用方法返回具体类型? - How to mock a generic method to return concrete type? 定义一个类MyClass <T> 或函数MyFunction <T> (T x)其中T只能通过实现IMyInterface的类型 - Define a class MyClass<T> or a function MyFunction<T>(T x) where T can only by a type that implements IMyInterface 类在C#中将接口实现为方法返回类型 - Class implementing interface as method return type in C#
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM