【问题标题】:Why can't a list of Interfaces use an implementing type?为什么接口列表不能使用实现类型?
【发布时间】:2010-10-31 07:06:46
【问题描述】:

一定有一些关于接口/泛型的基础知识我还没有学过。我希望现在能学会。

这是场景:

我有这个接口和类:

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

还有希望吗?你会怎么做?

【问题讨论】:

    标签: c# generics interface


    【解决方案1】:

    之所以会这样,是因为List&lt;RealValue&gt;是特定类型,没有继承List&lt;IInterface&gt;,所以无法转换。

    但是,在 .NET 4.0 中,您很幸运。接口IEnumerable&lt;out T&gt; 指定T 可以是类,也可以是基类,因此您可以将方法更改为:

    IEnumerable<IInterface> GetRealValues();
    

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

    out 关键字意味着两件事:

    1. 您在前面放置out 关键字的类型只能用于超出类的类型。所以,public T MyMethod() 是允许的,但public void MyMethod(T myParam) 是不允许的,因为这进入了类;

    2. 由于这个限制,.NET 知道T 可以被转换为从T 继承的所有内容。由于有限制,保证操作安全。

    【讨论】:

    • 这看起来不错。我将不得不深入了解out 对泛型类型参数的含义。不管怎样,我试过了,它奏效了。
    • 用更多关于 out 关键字的信息扩展了答案。
    • 甜蜜!感谢您的扩展答案!
    【解决方案2】:

    请注意,如果您可以将List&lt;RealValue&gt; 转换为List&lt;IInterface&gt;,您可以调用.Add(anyObjectImplementingIInterface),但这是无法使用的。

    不过,您可以使用.Cast&lt;IInterface&gt;().ToList()

    【讨论】:

      【解决方案3】:

      List&lt;RealValue&gt; 不能用于代替 List&lt;IInterface&gt;。如果允许,调用者将能够将IInterface 添加到返回的列表中,该列表的类型不是RealValue

      【讨论】:

        猜你喜欢
        • 2013-01-15
        • 2022-11-10
        • 1970-01-01
        • 2013-09-20
        • 2010-11-18
        • 2013-03-07
        • 2021-01-14
        • 2013-01-17
        • 1970-01-01
        相关资源
        最近更新 更多