一尘不染

返回派生类型时,“未实现接口”

c#

如下代码:

public interface ISomeData
{
    IEnumerable<string> Data { get; }
}

public class MyData : ISomeData
{
    private List<string> m_MyData = new List<string>();
    public List<string> Data { get { return m_MyData; } }
}

产生以下错误:

错误CS0738:“ InheritanceTest.MyData”未实现接口成员“
InheritanceTest.ISomeData.Data”。’InheritanceTest.MyData.Data’无法实现’InheritanceTest.ISomeData.Data’,因为它没有匹配的返回类型’System.Collections.Generic.IEnumerable’。

由于List 实现IEnumerable ,因此人们会认为我的类将实现该接口。有人可以解释不进行编译的基本原理吗?

如我所见,有两种可能的解决方案:

  1. 将接口更改为更具体,并要求实现IList。
  2. 更改我的类(MyData)以返回IEnumerable并实现原始接口。

现在假设我还有以下代码:

public class ConsumerA
{
    static void IterateOverCollection(ISomeData data)
    {
        foreach (string prop in data.MyData)
        {
            /*do stuff*/
        }
    }
}

public class ConsumerB
{
    static void RandomAccess(MyData data)
    {

        data.Data[1] = "this line is invalid if MyPropList return an IEnumerable<string>";
    }
}

我可以更改接口以要求实现IList(选项1),但这限制了可以实现该接口的人员以及可以传递给ConsumerA的类的数量。或者,我可以更改实现(类MyData),以便它返回IEnumerable而不是列表(选项2),但随后必须重写ConsumerB。

除非有人能启发我,否则这似乎是C#的缺点。


阅读 521

收藏
2020-05-19

共1个答案

一尘不染

不幸的是,返回类型必须匹配。您正在寻找的被称为“返回类型协方差”,而C#不支持。

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=90909

C#编译器团队的高级开发人员Eric Lippert在他的博客中提到,他们不打算支持返回类型协方差。

“这种差异称为“返回类型协方差”。正如我在本系列文章的前面部分提到的那样,(a)该系列与这种差异无关,并且(b)我们没有计划在C#。 ”

http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-
contravariance-part-twelve-to-infinity-but-not-
beyond.aspx

值得阅读Eric关于协方差和相反方差的文章。

http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx

2020-05-19