如何在C#中使用匿名接口回调方法作为参数?

时间:2014-01-28 20:31:04

标签: c# java callback unity3d

在Java中,我可以执行以下操作:

Java

public class Button {
    private Callback callback;

    public Button(Callback callback) {
        this.callback = callback;
    }

    public void update() {
        // Check if clicked..
        callback.onClick(this);
    }

    public interface Callback {
        public void onClick(Button Button);
    }
}

并使用它:

Button b = new Button(new Callback() {
    @Override
    public void onClick(Button b) {
        System.out.println("Clicked");
    }
});

我想知道,如果在(Unity)C#中可以做到这一点。

目前我的设置相同,语法正确

C#:

public class Button {
    private Callback callback;

    public Button(Callback callback) {
        this.callback = callback;
    }

    public void Update() {
        // Check if clicked..
        callback.OnClick(this);
    }

    public interface Callback {
        void OnClick(Button button);
    }
}

但是,当我在创建按钮时尝试执行相同操作时,

Button b = new Button(new Button.Callback() {
    void OnClick(Button button) {
        Debug.Log("Clicked");
    }
});

我收到的错误如下:

Unexpected symbol 'void'

error CS1526: A new expression requires () or [] after type

error CS8025: Parsing error

我尝试在界面中使用'virtual'或'abstract'方法,或在void OnClick之前添加'new'关键字(..当我创建按钮时,但到目前为止没有运气。

如果我从'new Button.Callback'中删除'()',似乎意外的符号'void'错误消失了

我会在这里感谢一些帮助。

3 个答案:

答案 0 :(得分:2)

您正在寻找Event handlers:

也许你想要这样的东西:

public delegate void Callback(Button btn);
public class Button
{

    public event Callback Click;
    public Button(Callback callback)
    {
        Click += callback;
    }

    public void Update()
    {
        // Check if clicked..
        if (Click != null)
        {
            Click(this);
        }
    }


}

用法:

Button btn = new Button( b => Debug.Log("Clicked"));

答案 1 :(得分:2)

在C#中,您无法尝试做什么(即匿名接口)。但是,您可以使用delegates来实现类似的功能,

public class Button {
    private Action<Button> action;

    public Button(Action<Button> action) {
        this.action = action;
    }

    public void Update() {
        // Check if clicked..
        action(this);
    }
}

然后,

Button b = new Button(delegate(Button button) { Debug.Log("Clicked"); });

或使用lambda表达式,使其看起来更简单,

Button b = new Button(button => Debug.Log("Clicked"));

Action基本上是表示函数的泛型类型,特别是返回类型为void的函数。因此,只要符合签名void Method(),您就可以传入现有方法。如果指定任何类型参数(使用Action<T>语法),则指定所表示的函数接受的参数的数量和类型,因此Action<Button>是一个返回void并接受的函数类型Button的单个参数,就像您的Callback.OnClick方法一样。

您可以传入符合预期签名的方法,而不是使用匿名委托或lambda表达式(例如,如上所述),

void OnClick(Button button)
{
     Debug.Log("Clicked");
}

并传递,

 Button b = new Button(OnClick);

答案 2 :(得分:2)

我认为您所需要的只是在最终类中实现您的界面:

public class SomeClass: Callback
{
    public SomeClass()
    {
       Button b = new Button(this);
    }


    void OnClick(Button button)
    {
        Debug.Log("Clicked");
    }

}