В качестве примечания, вы должны объявить B.Test()
метод как переопределение, но это другая проблема.
Комментирование строки base.Test();
исправляет ее.Вот моя теория.
Проблема в том, что вы реализуете B.Test()
, используя сгенерированный компилятором итератор.Частью процесса является взятие вашего кода и создание конечного автомата с использованием частного вложенного класса.Может показаться, что команда компиляторов не ожидала варианта использования, в котором вы бы назвали базовую реализацию чего-либо внутри итератора.
Таким образом, в действительности ваш код выглядит так:
class B : A<int>
{
public override IEnumerable<int> Test()
{
base.Test();
yield return 0;
}
}
потребуется итератор, созданный компилятором, и переведет ваши строки для создания соответствующего конечного автомата.Он не распознает вызов base
, поэтому он должен быть скопирован дословно.Сгенерированный класс, естественно, не наследуется ни от какого другого класса, поэтому вызов base
завершится неудачно.Концептуально, код конечного автомата будет где-то иметь строку:
[CompilerGenerated]
private sealed class <Test>d__0 : IEnumerable<T>, IEnumerable, IEnumerator<T>, IEnumerator, IDisposable
{
bool MoveNext()
{
// ...
base.Test(); // what, base?
// ...
}
}
Хотя, глядя на код, сгенерированный с помощью Reflector, он фактически не появляется в сборке (по крайней мере, я этого не вижу).
Я написал другой тестовый пример, чтобы определить, в какой строке это вызывает проблему:
System.Console.WriteLine("Starting");
using (var e = bb.GetEnumerator())
{
System.Console.WriteLine(e.MoveNext());
System.Console.WriteLine(e.Current);
System.Console.WriteLine(e.MoveNext());
}
И пошагово прошел по коду.Сбой при первом вызове MoveNext()
(как я бы подумал).К сожалению, я не знаю, как войти в сгенерированный итератор.Так что, шагая по разобранному коду, он выходит из строя в отмеченной строке:
System.Console.WriteLine("Starting");
00000075 mov ecx,dword ptr ds:[03622088h]
0000007b call 63474D1C
00000080 nop
using (var e = bb.GetEnumerator())
00000081 mov ecx,dword ptr [ebp-44h]
00000084 call dword ptr ds:[001E0020h]
0000008a mov dword ptr [ebp-58h],eax
0000008d mov eax,dword ptr [ebp-58h]
00000090 mov dword ptr [ebp-48h],eax
{
00000093 nop
System.Console.WriteLine(e.MoveNext());
00000094 mov ecx,dword ptr [ebp-48h]
00000097 call dword ptr ds:[001E0024h] // ERROR!!!!!!!!!!!!!!!!
0000009d mov dword ptr [ebp-5Ch],eax
000000a0 mov ecx,dword ptr [ebp-5Ch]
000000a3 call 63A48640
000000a8 nop
System.Console.WriteLine(e.Current);
000000a9 mov ecx,dword ptr [ebp-48h]
000000ac call dword ptr ds:[001E0028h]
000000b2 mov dword ptr [ebp-60h],eax
000000b5 mov ecx,dword ptr [ebp-60h]
000000b8 call 63A49388
000000bd nop
Так что, возможно, реальная проблема может быть в чем-то еще , но это, вероятно, будет связано с этим base
позвонить.