30

次のコードを参照してください。

public abstract class Base
{
    public virtual void Foo<T>() where T : class
    {
        Console.WriteLine("base");
    }
}

public class Derived : Base
{
    public override void Foo<T>()
    {
        Console.WriteLine("derived");
    }

    public void Bang()
    {
        Action bang = new Action(delegate { base.Foo<string>(); });
        bang();    //VerificationException is thrown
    }
}

new Derived().Bang();例外をスローします。取得したメソッドの生成された CIL 内Bang:

call instance void ConsoleApp.Derived::'<>n__FabricatedMethod1'<string>()

およびコンパイラが生成したメソッドの署名:

method private hidebysig 
    instance void '<>n__FabricatedMethod1'<T> () cil managed 
{
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
        01 00 00 00
    )       
    .maxstack 8

    IL_0000: ldarg.0
    IL_0001: call instance void ConsoleApp.Base::Foo<!!T>()
    IL_0006: ret
}

正しいコードは'<>n__FabricatedMethod1'<class T>. バグですか?ちなみに、delegate{ }(ラムダ式は同じ)を使わなくても、コードは構文シュガーで問題なく動作します。

Action good = new Action(base.Foo<string>());
good();  //fine

EDIT私はwindows8 RTM、.net Framework 4.5でVS2012 RTMRelを使用しています

編集このバグは修正されました。

4

2 に答える 2

3

バグとして確認され、現在修正されています

更新: Connect の記事はもう存在しません。バグが修正されました。

于 2012-12-14T07:52:00.863 に答える
1

最初は-これはこれを修正するための可能な方法ですが、おそらくあなたの質問に対する答えではありません。(ただし、コメントにはコード形式はありません)

これはこれに似ていると思います。外部変数トラップ。変数としてFoo()メソッドを使用していて、.NETにバグ(または機能)があるためです。

Bang()メソッドをこれに変更しようとしました

public void Bang()
{
    Action baseMethod = base.Foo<string>;
    Action bang = new Action(delegate { baseMethod(); });
    bang();    //VerificationException is thrown
}

そしてそれは機能し、結果は「ベース」です

少しお役に立てば幸いです。

于 2012-10-17T10:04:16.457 に答える