Подтвердить что ты не робот

Блоки и наследование итераторов

Для базового класса со следующим интерфейсом:

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

Однако меня приветствует предупреждение о том, что "доступ к члену через ключевое слово базы данных из итератора не может быть проверен".

Как принято решение этой проблемы?

4b9b3361

Ответ 1

Как насчет:

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

Ответ 2

Кстати, причиной этого нечетного поведения является то, что команда безопасности CLR сменила верификатор прямо перед отправкой v2, так что стало недействительным делать не виртуальный вызов виртуального метода одного класса из метода в другом класс.

Для дальнейшего объяснения этой проблемы см. мою статью по этому вопросу через несколько лет назад.

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

Теперь это устарело; мы исправили компилятор, чтобы теперь он создавал для вас помощник.

Ответ 3

Это потому, что итератор превращается в частный класс, а доступ к суперклассным методам из внутреннего класса не поддается проверке (поскольку он должен заставить указатель 'this' к чему-то другому, чем он сам).

Попробуйте создать новый закрытый метод в Derived:

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

и назовите это вместо base.GetListOfStuff()

Ответ 4

Кажется, что одним из решений было просто следовать указаниям "manual" : выполните вспомогательную функцию.

Итак, теперь я решил это следующим образом:

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

Но мне также интересны другие решения, если они существуют.