Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I create an open Delegate from a struct's instance method?

Tags:

c#

delegates

I have a struct with a private method that I'd like to invoke. Since I plan to do this in a performance critical section, I'd like to cache a delegate to perform the action. The problem is I can't seem to bind to its method with Delegate.CreateDelegate. The struct in question is not my creation and is used in interaction with a third party library. The struct in question looks like this::

public struct A
{
     private int SomeMethod()
     {
        //body go here
     }
}

And the following code will fail with an "Error binding to target method".

Delegate.CreateDelegate(typeof(Func<A,int>),typeof(A).GetMethod("SomeMethod",BindingFlags.Instance | BindingFlags.NonPublic));

I know I can write an expression tree to perform the action, but it seems odd that I can't use my normal goto for these things the Delegate.CreateDelegate method.

The above code works just fine if A were a class. The issue only arises because A is a struct. MSDN documentation is incorrect for this overload of CreateDelegate as it does work on non-static methods.

like image 870
Michael B Avatar asked Dec 01 '10 16:12

Michael B


People also ask

What is a class delegate?

A delegate is a reference type variable that holds the reference to a method. The reference can be changed at runtime. Delegates are especially used for implementing events and the call-back methods. All delegates are implicitly derived from the System. Delegate class.

What is a system delegate?

Namespace: System Assembly: System.Runtime.dll. Represents a delegate, which is a data structure that refers to a static method or to a class instance and an instance method of that class.

What is the role of delegate the net framework?

Delegates in C# NET object which points to a method that matches its specific signature. A delegate is a form of type-safe function pointer used by the Common Language Infrastructure. You create a delegate with the delegate keyword, followed by a return type and the signature of the methods that can be delegated to it.


1 Answers

Interesting problem. From this bug report, it looks like this might be a bug that will be fixed in a future version of .NET: http://connect.microsoft.com/VisualStudio/feedback/details/574959/cannot-create-open-instance-delegate-for-value-types-methods-which-implement-an-interface#details

EDIT: actually, I think this bug report is regarding a different issue, so the behavior you're seeing may not actually be a bug.

From that bug report, I gleaned that there is a work-around if you specify the first argument of your delegate as being passed by reference. Below is a complete working example:

public struct A
{
    private int _Value;

    public int Value
    {
        get { return _Value; }
        set { _Value = value; }
    }

    private int SomeMethod()
    {
        return _Value;
    }
}

delegate int SomeMethodHandler(ref A instance);

class Program
{
    static void Main(string[] args)
    {
        var method = typeof(A).GetMethod("SomeMethod", BindingFlags.Instance | BindingFlags.NonPublic);

        SomeMethodHandler d = (SomeMethodHandler)Delegate.CreateDelegate(typeof(SomeMethodHandler), method);

        A instance = new A();

        instance.Value = 5;

        Console.WriteLine(d(ref instance));
    }
}

EDIT: Jon Skeet's answer here also discusses this issue.

like image 120
Dr. Wily's Apprentice Avatar answered Nov 15 '22 12:11

Dr. Wily's Apprentice