Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does calling a generic local function with a dynamic parameter produce a BadImageFormatException?

Tags:

Playing around with C# 7's Local Functions, I ended up with some interesting behavior. Consider the following program:

public void Main()
{
    Console.WriteLine("Entered Main");
    DoSomething("");
}

private void DoSomething(object obj)
{
    Console.WriteLine("Entered DoSomething");
    Generic((dynamic)obj);
    GenericLocal(obj);
    GenericLocal((dynamic)obj); // This breaks the program

    void GenericLocal<T>(T val) => Console.WriteLine("GenericLocal");
}

private void Generic<T>(T val) => Console.WriteLine("Generic");

This produces:

Entered Main

... and then throws a BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B). Stack trace:

   at UserQuery.DoSomething(Object obj)
   at UserQuery.Main()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

(I'm running this in LINQPad, but I get similar results from dotnetfiddle.)

Removing the indicated line in the code yields the output you'd expect:

Entered Main
Entered DoSomething
Generic
GenericLocal

Can anyone explain why?

like image 406
StriplingWarrior Avatar asked Aug 03 '17 23:08

StriplingWarrior


2 Answers

This turned out to be a bug, but when the dotnet team looked into it they realized they can't easily fix things so local generic methods would work the way that non-local generic methods would. So instead they opted to make the compiler produce an error when you try to do this.

CS8322 Cannot pass argument with dynamic type to generic local function 'GenericLocal' with inferred type arguments.

like image 193
StriplingWarrior Avatar answered Sep 22 '22 18:09

StriplingWarrior


When you help the compiler a little the code will not break:

GenericLocal<dynamic>((dynamic)obj); // This doesn't break the program
like image 43
Piet Vredeveld Avatar answered Sep 22 '22 18:09

Piet Vredeveld