为什么接口列表不能使用实现类型?

时间:2010-10-31 07:06:46

标签: c# generics interface

我还没有学过关于接口/泛型的基本信息。我希望现在能够学习它。

以下是该方案:

我有这个界面和类:

public interface IInterface
{
    string TestValue { get; set; }
}

public class RealValue: IInterface
{
    public string TestValue { get; set; }
}

如果我创建一个这样的方法,它编译得很好:

public class RandomTest: IMethodInterface
{
   public IInterface GetRealValue()
   {
       RealValue realValue = new RealValue();
       return realValue;
   }
 }

请注意,我正在返回一个实现接口的对象。

现在,如果我向RandomTest类添加一个返回列表的方法,那么它就不再起作用了:

 public List<IInterface> GetRealValues()
 {
    List<RealValue> realValues = new List<RealValue>();
    return realValues;  // ERROR Here <- says it can't convert to a List<IInterface>
 }

所以,我的猜测是仿制药无法解决这个问题,但为什么呢?

有解决方法吗?当你实现上述方法的返回值时,你会怎么做?

public interface IMethodInterface
{
    IInterface GetRealValue();
    List<IInterface> GetRealValues(); // Can't just convert the return types to a concrete 
                                      // class because I am implementing this.  This 
                                      // interface is in a separate project that does not 
                                      // have the concrete classes.
}

有希望吗?你会做什么?

3 个答案:

答案 0 :(得分:10)

原因是List<RealValue>是一种特定类型,不会继承List<IInterface>,因此无法转换。

然而,在.NET 4.0中,你很幸运。接口IEnumerable<out T>指定T可以是类或基类,因此您可以将方法更改为:

IEnumerable<IInterface> GetRealValues();

在.NET 4.0上。请注意,这仅适用,因为IEnumerable在模板参数上指定了out关键字。

out关键字意味着两件事:

  1. 放置out关键字之前的类型只能用于类外的类型。因此,public T MyMethod()是允许的,但不允许public void MyMethod(T myParam),因为这会进入课堂;

  2. 由于这种限制,.NET知道可以将T包含在从T继承的所有内容中。由于这种限制,这可以确保安全操作。

答案 1 :(得分:3)

请注意,如果您可以将List<RealValue>转换为List<IInterface>,则可以致电.Add(anyObjectImplementingIInterface),但这无效。

但是,您可以使用.Cast<IInterface>().ToList()

答案 2 :(得分:1)

不能使用List<RealValue>代替List<IInterface>。如果允许,则调用者可以将IInterface添加到返回的列表中,该列表的类型不是RealValue