0

I have the following program:

class MyClass
{

    public static Dictionary<string, Func<string, string, string>> FuncMap;

    static MyClass()
    {
        FuncMap = new Dictionary<string, Func<string, string, string>>();

        FuncMap.Add("testing", (x,y) => x + " " + y);
    }

    public string Foo()
    {
        MethodInfo func = FuncMap["testing"].Method;

        var t = Expression.Lambda<Func<string>>(Expression.Call(func, new Expression[]
        {
            Expression.Constant("testing"),
            Expression.Constant("testing 2")
        })).Compile();

        return t();
    }
}

class Program
{

    static void Main(string[] args)
    {
        var inst = new MyClass();

        Console.WriteLine(inst.Foo());
    }
}

When I compile this in Visual Studio 2013 it works with no issue but when compiled in Visual Studio 2015 with RyuJIT I get the following exception:

Unhandled Exception: System.ArgumentException: Static method requires null instance, non-static method requires non-null instance.

Is this a bug with RyuJIT? Are there any work arounds?

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
Mikeb
  • 781
  • 7
  • 24
  • Why do you believe that this is related to RyuJIT instead of Roslyn? – Theodoros Chatzigiannakis Sep 08 '15 at 17:19
  • 1
    I think it is unlikely that it is caused by RyuJIT but this hypothesis is easy to test. Run it in 32-bit. RyuJIT is only enabled for 64-bit. – Mike Zboray Sep 08 '15 at 17:23
  • Not a RyuJIT bug, this dies when targeting x86 as well. MSIL code generation does not look healthy, you need to file a bug at github. – Hans Passant Sep 08 '15 at 17:30
  • 1
    My bad, yeah this is a Roslyn bug for sure not a RyuJIT issue. I've submitted a bug https://github.com/dotnet/roslyn/issues/5075 – Mikeb Sep 08 '15 at 17:34
  • Hmm, it looks like the delegate is generated differently. The C#5 compiler implements the lambda as a static method. The C#6 compiler implements it as an instance method of a compiler generated class. You shouldn't be binding to the method directly anyhow, you should be `Invoke()`ing it instead. – Jeff Mercado Sep 08 '15 at 17:40
  • @JeffMercado You are correct. This was an intentional change by the Roslyn team. See answer: http://stackoverflow.com/a/31411479/1148915 – deloreyk Sep 08 '15 at 20:43

1 Answers1

1

Looks like this is by design https://github.com/dotnet/roslyn/issues/5075

To fix the above code replace Expression.Call with Expression.Invoke.

Mikeb
  • 781
  • 7
  • 24