简体   繁体   English

返回接口类型列表

[英]Return list of interface type

I have three clasess that inherit from the same interface: 我有三个继承自相同界面的clasess:

Apple:Resource
Banana:Resource
Orange:Resource

I another class I have lists with the type op each one: 我在另一个类中列出了每个类型为op的类型:

private List<Apple> apples = new List<Banana>();
private List<Banana> bananas = new List<Empleado>();
private List<Orange> oranges = new List<Orange>();

Now I want a method that can return any of those lists, lets say something like this: 现在我想要一个可以返回任何列表的方法,让我们这样说:

public List<Resource> getListOf(string resource)
{
    switch (resource)
    {
        case "apple": 
            return apples;
            break;
        case "bananas":
        return bananas;
            break;
        case "oranges":
        return oranges;
            break;
        default:
            Console.WriteLine("wrong fruit");
            break;
    }
}

This gives me the following error: 这给了我以下错误:

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

I thought it would work the same manner as I can do: 我认为它的工作方式与我能做的相同:

foreach (Resource r in Fruitlist) {
    r.Meth();
}

The feature that makes the code break by its absence is called generic type covariance . 使代码中断的特征称为泛型类型协方差 C# does support variance in generics , but only in interfaces (not concrete classes). C#支持泛型中的差异 ,但仅支持接口(不是具体类)。

The foreach snippet works because it treats Fruitlist as an IEnumerable<Fruit> , and since that's a generic interface with an out (covariant) type parameter the compiler can view it as an IEnumerable<Resource> . foreach片段之所以有效,是因为它将Fruitlist视为IEnumerable<Fruit> ,因为这是一个带有out (协变)类型参数的通用接口,编译器可以将其视为IEnumerable<Resource>

If it's acceptable for getListOf to return an IEnumerable<Resource> then changing the function signature will make the code compile. 如果getListOf返回IEnumerable<Resource>是可以接受的,那么更改函数签名将使代码编译。 Otherwise the compiler would not be able to guarantee type safety, because you could write this code: 否则编译器将无法保证类型安全,因为您可以编写此代码:

List<Resource> apples = this.getListOf("apple");
apples.Add(new Orange()); // adding a Resource to a List<Resource>, right?

Another option would be to return a non-generic type, in which case type safety would be again lost and the compiler would introduce runtime checks to make sure that you don't mix apples with oranges (but at least the code would work if it's well-behaved). 另一种选择是返回非泛型类型,在这种情况下,类型安全性将再次丢失,编译器将引入运行时检查以确保您不将苹果与橙子混合(但至少代码可以工作,如果它是行为良好)。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM