This question already has an answer here:
In Java, I'm able to do the following:
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);
}
}
And use it like:
Button b = new Button(new Callback() {
@Override
public void onClick(Button b) {
System.out.println("Clicked");
}
});
And I'm wondering, if the same is possible in (Unity) C#.
Currently I have the same setup, with the correct syntax
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);
}
}
However, when I try to do the same when creating a button,
Button b = new Button(new Button.Callback() {
void OnClick(Button button) {
Debug.Log("Clicked");
}
});
I get errors like:
Unexpected symbol 'void'
error CS1526: A new expression requires () or [] after type
error CS8025: Parsing error
I've tried making the method 'virtual' or 'abstract' in the interface, or adding the 'new' keyword before void OnClick(.. when I create the button, but no luck so far.
It seems that the unexpected symbol 'void' error dissapears if I remove the '()' from 'new Button.Callback'
I would appreciate some help here.
What you are trying to do (i.e. anonymous interfaces) is not possible in C#. However, you could use delegates
to achieve something similar,
public class Button {
private Action<Button> action;
public Button(Action<Button> action) {
this.action = action;
}
public void Update() {
// Check if clicked..
action(this);
}
}
Then,
Button b = new Button(delegate(Button button) { Debug.Log("Clicked"); });
Or using a lambda expression, which makes it look simpler,
Button b = new Button(button => Debug.Log("Clicked"));
Action
is basically a generic type that represents a function, specifically a function with return type of void
. Thus you can pass in existing methods as long as they comply with the signature void Method()
. If you specify any type parameters (using the Action<T>
syntax) you are specifying the number and types of arguments the represented function accepts, thus Action<Button>
is a function that returns void
and takes in a single argument of type Button
, just like your Callback.OnClick
method.
Instead of using an anonymous delegate or a lambda expression (e.g. like above), you can pass in a method that complies with the expected signature,
void OnClick(Button button)
{
Debug.Log("Clicked");
}
and pass it,
Button b = new Button(OnClick);
Action
a build in class or a custom made class that handles the button clicks? - Snakybovoid
. Thus you can pass in existing methods as long as they comply with the signature void Method(Button button)
- rae1
You are looking for Event handlers:
Maybe you want something like this:
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);
}
}
}
Usage:
Button btn = new Button( b => Debug.Log("Clicked"));
I think all you need is to implement your interface in final class like this:
public class SomeClass: Callback
{
public SomeClass()
{
Button b = new Button(this);
}
void OnClick(Button button)
{
Debug.Log("Clicked");
}
}