.NET Linq to Objects 奇怪的行为
我在下面的小代码中遇到了 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;
}
}
}
有什么想法为什么它不起作用吗?
I've got a BadImageFormatException error in this little code below. I know it isn't good practice to write a program in this way but it seems to be a bug in .NET Framework, not in my code.
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;
}
}
}
Any ideas why it doesn't work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
作为旁注,您应该将
B.Test()
方法声明为重写,但这是一个不同的问题。注释掉
base.Test();
行即可修复该问题。这是我的理论。问题是您正在使用编译器生成的迭代器实现
B.Test()
。该过程的一部分是获取代码并使用私有嵌套类创建状态机。编译器团队似乎没有想到您会调用迭代器中任何内容的基本实现的用例。因此,实际上您的代码如下所示:
将需要编译器创建的迭代器,并将翻译您的行以创建适当的状态机。它无法识别
base
调用,因此必须逐字复制。生成的类自然不会从任何其他类继承,因此base
调用将会失败。从概念上讲,状态机代码将在某处包含以下行:尽管查看使用 Reflector 生成的代码,但它实际上并未出现在程序集中(至少我没有看到它)。
我编写了一个不同的测试用例来确定哪一行导致了问题:
并逐步执行了代码。它在第一次
MoveNext()
调用时失败(正如我所想的那样)。不幸的是我不知道如何进入生成的迭代器。因此,单步执行反汇编代码,它会在标记行上失败:因此,实际问题可能是其他问题,但它可能与此基本调用有关。
As a side note, you should be declaring
B.Test()
method as an override, but that's a different issue.Commenting out the line
base.Test();
fixes it. Here's my theory.The problem is that you are implementing
B.Test()
using a compiler generated iterator. Part of the process is taking your code and creating a state machine using a private nested class. It would appear that the compiler team did not expect a use case where you would call the base implementation of anything within the iterator.So in effect your code which is like this:
will require an iterator created by the compiler and will translate your lines to make an appropriate state machine. It does not recognize the
base
call so it must have been copied verbatim. The generated class naturally wouldn't inherit from any other class therefore thebase
call would fail. Conceptually, the state machine code will have the line somewhere:Though looking at the code generated using Reflector it doesn't actually appear in the assembly (at least, I don't see it).
I wrote a different test case to determine what line it causes a problem:
And stepped through the code. It fails on the first
MoveNext()
call (as I would have thought). Unfortunately I don't know how to step into the generated iterator. So stepping through the disassembled code, it fails on the marked line:So maybe the actual problem might be something else but it'll probably be related to this
base
call.干得好。
您需要创建一个委托方法来调用 base.Test() 方法。
此外,您还应该使用 Test 方法作为替代方法或新方法。
供参考。
http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k(EHBADIMAGEFORMAT);k(TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERSION% 3dV4.0%22);k(DevLang-CSHARP)&rd=true
Here you go.
you need to create a delegate method to call the base.Test() method.
Also you should use the Test method as override or new.
For reference.
http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k(EHBADIMAGEFORMAT);k(TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERSION%3dV4.0%22);k(DevLang-CSHARP)&rd=true