我在下面的这个小代码中遇到了BadImageFormatException错误。我知道以这种方式编写程序并不是一个好习惯,但它似乎是.NET Framework中的一个错误,而不是我的代码中的错误。
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var b = new B();
var bb = b.Test();
var bbb = bb.Count();
}
}
class A<T>
{
public virtual IEnumerable<T> Test()
{
yield return default(T);
}
}
class B : A<int>
{
public IEnumerable<int> Test()
{
base.Test();
yield return 0;
}
}
}
为什么它不起作用的任何想法?
答案 0 :(得分:3)
作为旁注,您应该声明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
电话有关。
答案 1 :(得分:0)
你走了。 您需要创建一个委托方法来调用base.Test()方法。 您还应该使用Test方法作为覆盖或新的。
class A<T>
{
public virtual IEnumerable<T> Test()
{
yield return default(T);
}
}
class B : A<int>
{
public new IEnumerable<int> Test()
{
this.MyDelegate();
yield return 0;
}
private void MyDelegate()
{
base.Test();
}
}
public class CompassModel
{
public void GetTeamLeadData()
{
var b = new B();
var bb = b.Test();
var bbb = bb.Count();
}
}