What are the differences (if any) between the two lines of code shown below.
Are there benefits to one instead of the other?
public event Action myEventAction;
public Action myAction;
What are the differences (if any) between the two lines of code shown below.
Are there benefits to one instead of the other?
public event Action myEventAction;
public Action myAction;
They are completely different…
The first is declaring an event that uses an Action as the delegate type. That means listeners to the event will use an Action to react when the event is invoked.
The second is just a variable of type Action.
You’re comparing Apples and Oranges here.
Read about C# events here: https://www.tutorialsteacher.com/csharp/csharp-event
So what does the other line do then?
I feel he may have been overstating the difference between the two. From the point of view of “the guy that writes the C# compiler” they’re wildly different, but to you they are very similar. The most important difference: “event” has multiple subscribers, while the other one is a single “subscriber”. You can think of the “event” version kind of like an array of delegates (not exactly, but close). So let’s say you have this:
public Action doThing;
void Awake() {
doThing = PrintA;
}
void Update() {
if (Input.GetKeyDown(KeyCode.A)) doThing = PrintB;
doThing();
}
void PrintA() {
Debug.Log("A");
}
void PrintB() {
Debug.Log("B");
}
“doThing” here points to a function. It points to PrintA at first, then points to PrintB after you press a button. You can invoke it like a function, and it calls one or the other.
Now, consider this:
public event Action doThings;
void Awake() {
}
void Update() {
if (Input.GetKeyDown(KeyCode.A)) doThings += PrintA;
if (Input.GetKeyDown(KeyCode.B)) doThings += PrintB;
doThings();
}
Now, doThings can do any number of functions. You can add and remove delegates (called “listeners” in this case), and all of them will be called when you call doThings().
Note that you can’t do:
doThings = PrintA;
You can only add and remove listeners, not assign outright. You also can’t copy the listeners of one event to another, and events must always be public members of a class. But aside from the usage restrictions, they do behave fairly similarly to delegates.
Delegates are more versatile in a lot of ways, since they can be passed around like variables and such. For example, pass one in as a parameter to a coroutine, and you can execute arbitrary code after the coroutine is done.
So to summarise, are you saying that: public Action myAction; can basically only have one listener.
While: public event Action myEvent;
Can have multiple listeners?
@StarManta that’s an interesting way of putting it. Conceptually I differentiate delegates and events in my head, but I suppose you’re right that a delegate can certainly behave as a single-listener event. I think you also covered the other ways in which delegates are a lot more flexible than that too. Another difference: only the “owner” of an event can invoke that event, but anyone can invoke a delegate.
No, those two lines are very close to the same thing. All delegates in C# are multicast delegates, i.e. they can be combined and removed using the += and -= operators. Every delegate in C# can be a combination of multiple delegates, just like events.
The C# documentation says regarding events:
And that’s basically it. The event keyword allows everyone with access to the event to add/remove delegates but limits invoking and overwriting to the private scope of the class/struct (it also turns it into a kind of property that allow to override the add and remove accessor blocks but that’s a rarely used feature).
public Action exampleDelegate;
public event Action exampleEvent;
// Add/Remove works the same for both
exampleDelegate += myMethod;
exampleEvent += exampleEvent;
exampleDelegate -= myMethod;
exampleEvent -= exampleEvent;
// The delegate can be invoked/set from anywhere
if (exampleDelegate != null) {
exampleDelegate();
exampleDelegate = null;
}
// The event only within the declaring class/struct
if (exampleEvent != null) {
exampleEvent();
exampleEvent = null;
}