Подтвердить что ты не робот

Компилятор генерировал неверный код для анонимных методов [MS BUG FIXED]

Смотрите следующий код:

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{ } (lambda-выражение одно и то же) код отлично работает с синтаксическими сахарами.

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

РЕДАКТИРОВАТЬ Я использую VS2012 RTMRel в RTM для Windows8,.NET Framework 4.5

EDIT Теперь эта ошибка исправлена: http://connect.microsoft.com/VisualStudio/feedback/details/766845/vs2012-the-compiler-generated-incorrect-codes-for-anonymous-methods

4b9b3361

Ответ 2

Сначала - это возможный способ исправить это, но, вероятно, не ответ на ваш вопрос. (Но комментарии не содержат кода)

Я считаю, что это похоже на это: Внешняя ловушка переменной, потому что вы используете метод Foo() как переменную, и есть ошибка (или, может быть, функция ) в .NET

Я попытался изменить метод Bang() на этот

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

И он работает, и результат "base"

Надеюсь, это немного поможет.