迭代器块和继承

18

有一个具有以下接口的基类:

public class Base
{
    public virtual IEnumerable<string> GetListOfStuff()
    {
        yield return "First";
        yield return "Second";
        yield return "Third";
    }
}

我想创建一个派生类,重写基类的方法,并添加自己的东西,像这样:

public class Derived : Base
{
    public override IEnumerable<string> GetListOfStuff()
    {
        foreach (string s in base.GetListOfStuff())
        {
            yield return s;
        }

        yield return "Fourth";
        yield return "Fifth";
    }
}

然而,我收到了一个警告:“无法验证通过迭代器使用基本关键字访问成员”。

那么这个问题的解决方案是什么呢?


6
请注意,这个问题在C# 4中已经解决了(可能在C# 3 SP 1中也有解决?我不记得我们是否曾经解决过这个问题。我们本来就是打算解决它的)。现在编译器会为你生成辅助程序。 - Eric Lippert
我在VS2008 SP1中收到了警告。 - Dave Van den Eynde
5个回答

12

怎么样:

public class Derived : Base
{
    public override IEnumerable<string> GetListOfStuff()
    {
        return base.GetListOfStuff().Concat(GetMoreStuff());        
    }
    private IEnumerable<string> GetMoreStuff()
    {
        yield return "Fourth";
        yield return "Fifth";
    }
}

不要为基础内容编写辅助函数,而是为此类中的内容编写辅助函数。好主意! - Dave Van den Eynde

9

4

看起来一个解决方案就是简单地按照“手册”上所说的做法:创建一个辅助函数。

因此,我现在是这样解决的:

public class Derived : Base
{
    private IEnumerable<string> GetBaseStuff()
    {
        return base.GetListOfStuff();
    }

    public override IEnumerable<string> GetListOfStuff()
    {
        foreach (string s in GetBaseStuff())
        {
            yield return s;
        }

        yield return "Fourth";
        yield return "Fifth";
    }
}

但我对其他解决方案也很好奇,如果有的话。


3

这是因为迭代器被转换为私有类,从内部类访问超类方法是不可验证的(因为它必须将“this”指针强制为其他内容而不是自身)。

尝试在Derived中创建一个新的私有方法:

private IEnumerable<string> GetBaseListOfStuff()
{        
    return base.GetListOfStuff();
}

调用那个函数而不是base.GetListOfStuff()


-2

如果有人仍在寻找答案。我遇到了同样的问题,并通过以下方式解决:

public class Derived : Base
{
    public override IEnumerable<string> GetListOfStuff()
    {
        var enumerator = base.GetListOfStuff().GetEnumerator();

        while(enumerator.MoveNext())
        {
             yield return enumerator.Current;
        }

        yield return "Fourth";
        yield return "Fifth";

        yield break;
    }
}

这基本上就是我的答案,直接使用枚举器而不是 foreach - Dave Van den Eynde

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接