Iterator blocks and inheritance

前端 未结 4 1876
無奈伤痛
無奈伤痛 2021-02-13 01:47

Given a base class with the following interface:

public class Base
{
    public virtual IEnumerable GetListOfStuff()
    {
        yield return \"F         


        
相关标签:
4条回答
  • 2021-02-13 02:18

    How about:

    public class Derived : Base
    {
        public override IEnumerable<string> GetListOfStuff()
        {
            return base.GetListOfStuff().Concat(GetMoreStuff());        
        }
        private IEnumerable<string> GetMoreStuff()
        {
            yield return "Fourth";
            yield return "Fifth";
        }
    }
    
    0 讨论(0)
  • 2021-02-13 02:23

    It's because the iterator gets turned into a private class, and accessing superclass methods from an inner class is not verifiable (as it has to force the 'this' pointer to something other than itself).

    Try creating a new private method in Derived:

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

    and call that instead of base.GetListOfStuff()

    0 讨论(0)
  • 2021-02-13 02:27

    Incidentally, the reason for this odd behaviour is that the CLR security team changed the verifier right before v2 shipped, such that it became unverifiable to do a non-virtual call on a virtual method of one class from a method in a different class.

    For further explanation of this issue see my article on the subject from a few years back.

    http://blogs.msdn.com/ericlippert/archive/2005/11/14/why-are-base-class-calls-from-anonymous-delegates-nonverifiable.aspx

    This is now out-of-date; we've fixed up the compiler so that it now generates the helper for you.

    0 讨论(0)
  • 2021-02-13 02:39

    It seems that one solution was to simply follow what the "manual" says: make a helper function.

    So for now I've solved it like this:

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

    But I'm curious about other solutions as well, should they exist.

    0 讨论(0)
提交回复
热议问题