Search code examples
c#delegatesunity-game-enginengui

Pass Method As EventDelegate


I am attempting to pass a method as a parameter. But I am getting a compiler error and I dont quite understand what I am doing wrong?

The compiler error is:

Argument `#1' cannot convert 'method group' expression to type 'EventDelegate'

public class AssignEventDelegate : MonoBehaviour {

    public UISprite sprite;

    public void AddOnFinish (EventDelegate method) {
        EventDelegate.Add (sprite.GetComponent<TweenScale>().onFinished, method);
    }
}

public class AssignEventDelegateOther : MonoBehaviour {

    // Use this for initialization
    void Start () {
        // Compiler error occurs below
        GameObject.Find ("Main Camera").gameObject.GetComponent<AssignEventDelegate>().AddOnFinish( myOnFinish ); 
    }

    public void myOnFinish () {
        Debugger.print ("myOnFinish");
    }
}

Solution

  • First let's make sense of the error message. It should be clear that the problematic part of that line is

    .AddOnFinish( myOnFinish );
    

    So what's a method group? That has been answered here before. In short, it is what the compiler calls a bare reference to a method name that does not include () or any argument list. You can't use a method group on its own. It does not have any representation in the CLR. Its a method "group" because, at least in theory, it represents a set of methods that the compiler will have to do overload resolution on. The compiler knows how to turn method groups (also lambdas and anonymous methods) into specific delegate types, but that's it. myOnFinish is a method group, but here it really only contains a single method.

    A quick look at the NGUI docs tells me that contrary to its name, EventDelegate is not a delegate type but simply a class that is meant to wrap a delegate.

    So there we have it. The compiler has no idea how to convert a method group to this EventDelegate class and it produces an error.

    To fix it, we need to provide the conversion. Which it turns out, would just be calling the constructor of EventDelegate:

    .AddOnFinish( new EventDelegate(myOnFinish) );
    

    This works since the constructor takes an instance of EventDelegate.Callback which is delegate type that is compatible with myOnFinish.