Блоки и наследование итераторов
Для базового класса со следующим интерфейсом:
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";
}
}
Однако меня приветствует предупреждение о том, что "доступ к члену через ключевое слово базы данных из итератора не может быть проверен".
Как принято решение этой проблемы?
Ответы
Ответ 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";
}
}
Но мне также интересны другие решения, если они существуют.