Como nota al margen, debe declarar el método B.Test()
como una anulación, pero ese es un problema diferente.
Comentando la línea base.Test();
lo corrige. Aquí está mi teoría
El problema es que está implementando B.Test()
utilizando un iterador generado por el compilador. Parte del proceso es tomar su código y crear una máquina de estado usando una clase privada anidada. Parece que el equipo del compilador no esperaba un caso de uso en el que llamaras a la implementación base de cualquier cosa dentro del iterador.
Así pues, en efecto, que su código es así:
class B : A<int>
{
public override IEnumerable<int> Test()
{
base.Test();
yield return 0;
}
}
requerirá un iterador creado por el compilador y se traducirá sus líneas para hacer una máquina de estado apropiado. No reconoce la llamada base
, por lo que debe haber sido copiada textualmente. La clase generada, naturalmente, no heredaría de ninguna otra clase, por lo que la llamada base
fallaría. Conceptualmente, el código máquina de estado tendrá la línea en alguna parte:
[CompilerGenerated]
private sealed class <Test>d__0 : IEnumerable<T>, IEnumerable, IEnumerator<T>, IEnumerator, IDisposable
{
bool MoveNext()
{
// ...
base.Test(); // what, base?
// ...
}
}
Aunque mirando el código generado usando Reflector no aparece realmente en la asamblea (por lo menos, yo no lo veo).
escribí un caso de prueba diferentes para determinar cuál es la línea que causa un problema:
System.Console.WriteLine("Starting");
using (var e = bb.GetEnumerator())
{
System.Console.WriteLine(e.MoveNext());
System.Console.WriteLine(e.Current);
System.Console.WriteLine(e.MoveNext());
}
y dio un paso a través del código. Falla en la primera llamada MoveNext()
(como hubiera pensado). Lamentablemente, no sé cómo ingresar al iterador generado. Así que paso a paso por el código desensamblado, falla en la línea marcada:
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
Así que tal vez el problema real podría ser otra cosa pero que probablemente va a estar relacionado con este base
llamada.
Ese es un problema muy poco probable de obtener solo de lógica, y es muy poco probable que sea un error .NET. ¿Qué cambios tiene que hacer para que el código se ejecute (en otras palabras, qué cambio específico desencadena el problema)? –
Aunque puedo reproducir el problema. Interesante ... –
¿Dónde está Skeet o Lippert? –