【问题标题】:Return list of interface type返回接口类型列表
【发布时间】:2013-06-11 16:16:06
【问题描述】:

我有三个继承自同一个接口的类:

Apple:Resource
Banana:Resource
Orange:Resource

我在另一个类中列出了每个类型为 op 的列表:

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

现在我想要一个可以返回任何这些列表的方法,让我们这样说:

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;
    }
}

这给了我以下错误:

不能隐式转换类型 'System.Collections.Generic.List&lt;Fruits.Apple&gt;' 到 'System.Collections.Generic.List&lt;Fruits.Resource&gt;'

我认为它会以与我一样的方式工作:

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

【问题讨论】:

  • 您可以使用“私有列表 x = new List();”为您的成员,然后在您的函数中返回它们。然后在需要它们的真实类型(使用 is 和 as)时对其进行测试和转换。

标签: c# class oop inheritance interface


【解决方案1】:

使代码因缺少而中断的特性称为泛型协方差。 C# 确实支持variance in generics,但仅在接口中(不是具体类)。

foreach sn-p 之所以有效,是因为它将Fruitlist 视为IEnumerable&lt;Fruit&gt;,并且由于这是一个带有out(协变)类型参数的通用接口,编译器可以将其视为IEnumerable&lt;Resource&gt;

如果getListOf 返回IEnumerable&lt;Resource&gt; 是可以接受的,那么更改函数签名将使代码编译。否则编译器将无法保证类型安全,因为您可以编写以下代码:

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

另一种选择是返回非泛型类型,在这种情况下,类型安全性将再次丢失,编译器将引入运行时检查以确保您不会将苹果与橙子混为一谈(但至少代码会如果它表现良好,就可以工作)。

【讨论】:

  • 谢谢乔恩,首先它起作用了,太棒了:) 但我仍然不确定这个例子,使用 IEnumerable 而不是接口如何让我在列表中添加错误的类型?
  • @Trufa:关键是IEnumerable&lt;T&gt; 不允许您修改集合,这就是它能够协变的原因。如果它有任何接受T 作为参数的方法(而不是将其用作返回类型),那么它就不允许有out 类型参数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-10
  • 2011-08-08
  • 2011-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-10
相关资源
最近更新 更多