gpt4 book ai didi

.NET Linq to Objects 奇怪的行为

转载 作者:行者123 更新时间:2023-12-03 07:23:00 24 4
gpt4 key购买 nike

我在下面的小代码中遇到了 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;
}
}
}

有什么想法为什么它不起作用吗?

最佳答案

顺便说一句,您应该将 B.Test() 方法声明为重写,但这是一个不同的问题。

注释掉 base.Test(); 行可以修复它。这是我的理论。

问题是您正在使用编译器生成的迭代器实现B.Test()。该过程的一部分是获取代码并使用私有(private)嵌套类创建状态机。编译器团队似乎没有想到您会调用迭代器中任何内容的基本实现的用例。

所以实际上你的代码是这样的:

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

因此,也许实际问题可能是其他问题,但是它可能与此基本调用有关。

关于.NET Linq to Objects 奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6715640/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com