C
C#2y ago
wcasa

✅ Events and Delegates question..

what is the point of using Events and Delegates, if you can just create methods which will just call other methods?
77 Replies
sibber
sibber2y ago
Linq is the biggest example
santijlm
santijlm2y ago
The idea of a delegate is simple You just call the event once and every sript can subscribe to it And they can all change what happens when the event is invoked with += and -= you can add more functions to the event itself, so that when it's invoked more functions are executed
wcasa
wcasa2y ago
cant i do the same with just methods i can add lines of codes, directly into the method that call other methods can you give more details?
MODiX
MODiX2y ago
Cyberrex#8052
REPL Result: Success
int[] arr = { 1, 2, 3 };
return arr.Select(x => x * 2); // takes a delegate
int[] arr = { 1, 2, 3 };
return arr.Select(x => x * 2); // takes a delegate
Result: List<int>
[
2,
4,
6
]
[
2,
4,
6
]
Compile: 501.951ms | Execution: 74.936ms | React with ❌ to remove this embed.
Anton
Anton2y ago
with delegates you can dynamically configure what should be called look up what's polymorphism delegates are essentially equivalent to interfaces with a single method
FusedQyou
FusedQyou2y ago
One benefit of Events is that it's a way for children to pass information to parents. Alternatively it is also a solution where you need to pass information between two instances where one has a dependency with another and it needs to "subscribe" to anything that happends in it, which is basically the same thing as what I said firstly, but fancier. Delegate types are useful for when you need to pass it as a parameter for something like linq, which uses delegates to filter, select or do any other type of equation And yes, you can literally just pass a method instead
wcasa
wcasa2y ago
Yeah, kinda I still don't understand benefit of delegates and events over regular methods Method that holds several methods is quite literally same
Becquerel
Becquerel2y ago
the difference is that a delegate can point to different methods at runtime if you have a method that just calls other methods normally, that's set in stone at compile-time e.g...
int Add(int first, int second) { ... }
int Subtract(int first, int second) { ... }

var random = new Random();

Func<int, int, int> eitherAddOrSubtract = random.Next() % 2 == 0 ? Add : Subtract;
int Add(int first, int second) { ... }
int Subtract(int first, int second) { ... }

var random = new Random();

Func<int, int, int> eitherAddOrSubtract = random.Next() % 2 == 0 ? Add : Subtract;
the random.Next() % 2 bit just means 'flip a coin, either heads or tails' the code that eitherAddOrSubtract points to will be different every time you run this program and this is why LINQ is powerful. when some guy at Microsoft sat down to write .Where(), he didn't know all the things we'd be doing with it today. but because we can give .Where() our own functionality at runtime, he didn't have to
Anton
Anton2y ago
i just told you, it's polymorphism
Playboi17
Playboi172y ago
Events can dynamically add subscribers at runtime. With a method, you would have to put FunctionOne() and FunctionTwo() in at runtime.
canton7
canton72y ago
It's about who's got a reference to who. If a method in class A calls a method on class B, then class A needs to know about class B, and have a reference to it. If class B subscribes to an event on class A, then it's class B that knows about class A, and has a reference to it. Think of a UI element for example, like a Button. You want some code to be called when the button is clicked. The Button class knows nothing about your code (why should it? You want the same button to be used in multiple places), but your class knows about the button. So you can easily subscribe to an event on the button, and the button class doesn't need to know that it should call your e.g. LogIn method when it's clicked
FusedQyou
FusedQyou2y ago
In your example you might aswell just create a normal method out of it 😛 Delegates have their own benefits and if you don't see the point of them you clearly never encountered these benefits I suppose the idea of something being useless is reasonable if you never encountered a use, but most stuff in c# is there for a reason And if not, it probably exists as an alternative to an already existing feature, and it is up to you to choose what to use
wcasa
wcasa2y ago
what about creating button with 1 class, that has info only about button
canton7
canton72y ago
I don't follow what you mean
wcasa
wcasa2y ago
and create public methods, that will be called for each button? that will be global
canton7
canton72y ago
If you write a generic button, which can be placed anywhere on your UI, how should that button know what method to call when it's clicked?
wcasa
wcasa2y ago
oh, yeah thats true
canton7
canton72y ago
Why should it care what method is called? It shouldn't. It should just be told "When you're clicked, call this"
wcasa
wcasa2y ago
buuuuut, ig you can do smth like
if(btn1.click){
MethodForBtn1();
}
if(btn1.click){
MethodForBtn1();
}
canton7
canton72y ago
How does that bit of code get executed? How do you know when the button's been clicked, so you can run that code?
wcasa
wcasa2y ago
just an example, that doesnt have any logic, and only demonstrates idea
canton7
canton72y ago
Right but it's missing a critical concept
wcasa
wcasa2y ago
events?
canton7
canton72y ago
How the button tells your code that it's been clicked You can use events, or a list of methods, or a list of classes each of which implements an interface which has a "button clicked" method, or a message broker, or any other pub/sub system Almost every language has a way to do this
wcasa
wcasa2y ago
hmm what about making everything global?
sibber
sibber2y ago
that leads to unmaintainable spaghetti code
canton7
canton72y ago
How would making everything global help? Even if your "log in" button is global, it doesn't mean that it's been written to know what method to call when it's clicked
wcasa
wcasa2y ago
ok, one more question, what is the point of event ? delegate - has references to methods, can *call *them when smth happens
canton7
canton72y ago
That's the same as asking what the point of a property is. Why not just use fields
wcasa
wcasa2y ago
events - *notifies *every subscriber that smth happend
canton7
canton72y ago
A property wraps a field, and lets you control who can set and who can read, add your own code to the getter/setter, etc. Same with events: they wrap a delegate field, let you control who can subscribe/unsubscribe or raise the event (importantly!), and add your own code to the add/remove accessors
wcasa
wcasa2y ago
well property gives you new abilities that field cant do, but as i understand (most likely wrong) delegate can do everything that event can do
canton7
canton72y ago
It's the same distinction. A property is a pair of get/set methods which wrap a field. An event is a pair of add/remove methods which wrap a field that's a delegate And they exist for the same reason that properties exist
wcasa
wcasa2y ago
1) let you control who can subscribe/unsubscribe or raise the event isnt it possible to do with += and -= for delegate? 2)*and add your own code to the add/remove accessors * is it done in order to filter things?
canton7
canton72y ago
(the main reason is to stop someone outside of your class from raising your events. People outside can only subscribe, and can only unsubscribe themselves - they can't unsubscribe other people)
Anton
Anton2y ago
control access in a standard way
canton7
canton72y ago
If you just used a delegate field, without the event wrapper, anyone could raise the event, and anyone could unsubscribe other people
Anton
Anton2y ago
properties do get set in a standard way events do add remove
wcasa
wcasa2y ago
they can't unsubscribe other people is it for events?
Anton
Anton2y ago
imo making delegates multicast was a design mistake, also they should've been value types
wcasa
wcasa2y ago
idk, imo it gives you more possibilities
canton7
canton72y ago
Yes. An event stops you from unsubscribing other people.
wcasa
wcasa2y ago
other people - methods from other classes?
canton7
canton72y ago
Eh, you wouldn't be able to do CAS when modifying if they were value types. Which would make access more expensive Yes
Anton
Anton2y ago
cas?
wcasa
wcasa2y ago
ohh, thats good point, i am always used to writing all methods in class Program (main class)
canton7
canton72y ago
Compare and swap. The impl of add/remove uses CompareExchange to avoid a lock
wcasa
wcasa2y ago
thanks canton7, you helped me a lot dont you mind if i close chat? looks like you have conversation
Anton
Anton2y ago
you mean it checks pointers? it can't possibly work that way tho, unless they also implicitly cache delegates for same methods on same objects
canton7
canton72y ago
Look at the impl of an event on sharplab Delegates are immutable reference types
Anton
Anton2y ago
well are you saying if I do
var a = obj.A;
var b = obj.A;
var a = obj.A;
var b = obj.A;
these would be the same reference?
canton7
canton72y ago
It does the CAS when creating a new delegate with the new subscriber, and swapping that into the delegate field backing the event
Anton
Anton2y ago
how do they cache the reference?
wcasa
wcasa2y ago
btw, it doesnt, right?
Anton
Anton2y ago
I would guess no
canton7
canton72y ago
Look, this is common knowledge. It's very easy to see what the compiler does here. Just open up SharpLab, create an event, look at the decompiled C code
Anton
Anton2y ago
easier said than done when you're on phone lol
canton7
canton72y ago
Yeah, I am too which is why I haven't pasted it 😆
add
{
EventHandler eventHandler = this.E;
while (true)
{
EventHandler eventHandler2 = eventHandler;
EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value);
eventHandler = Interlocked.CompareExchange(ref this.E, value2, eventHandler2);
if ((object)eventHandler == eventHandler2)
{
break;
}
}
}
add
{
EventHandler eventHandler = this.E;
while (true)
{
EventHandler eventHandler2 = eventHandler;
EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value);
eventHandler = Interlocked.CompareExchange(ref this.E, value2, eventHandler2);
if ((object)eventHandler == eventHandler2)
{
break;
}
}
}
Classic CAS And two delegates created from the same method compare equal (but not necessarily those from two lambdas, which is a gotcha). But that's only relevant inside Delegate.Combine / Delegate.Remove and isn't relevant to the CAS in the add/remove handlers
wcasa
wcasa2y ago
oh, btw when i used to be complete toddler in programming, i thought that classes are meanengless, because, instead of just using properties with classes, i used to create variables, and connect them by my own, like int Object1Age, Object2Age and string Object1String, Object2String, which is not as convinient as classes . As i understand, this post has kinda same vibes. Instead of creating events, i used method that call methods, which is not as convenient as events
canton7
canton72y ago
Events only make sense when you have multiple classes. There's very rarely any need to use events within a single class
wcasa
wcasa2y ago
in case of single class, delegates are good option, right?
sibber
sibber2y ago
delegates solve a different problem
Anton
Anton2y ago
I don't understand this code, but it looks as if it would make tons of garbage
wcasa
wcasa2y ago
generally, delegates are created for making code easier to read/understand and write? cause delegates is just like object that holds method. Which is easier to understand than method that calls methods (and its not convinient to add new methods into that method)
sibber
sibber2y ago
no
wcasa
wcasa2y ago
fuck
canton7
canton72y ago
Not really no. It'll create a new delegate instance every time you add a new subscriber, unless there's a race
wcasa
wcasa2y ago
why not
sibber
sibber2y ago
delegates were created because we wanted to use functions as variables thats all there is to it
wcasa
wcasa2y ago
yeah, but from other perspective, it also makes reading/writing code easier (kinda)
Anton
Anton2y ago
you're talking about anonymous functions, which is not the same as delegates anonymous functions make dealing with context automatic and let you type less code
wcasa
wcasa2y ago
oh, ok aaaand, last quesiton
wcasa
wcasa2y ago
wcasa
wcasa2y ago
why does event raiser must be virtual?
canton7
canton72y ago
Well, they are rather related... Convenience. It lets subclasses tell when the event is being raised without needing to subscribe to it, by overriding that method
wcasa
wcasa2y ago
ohhhh wooww, it is cool catpog guys, you really helped me!!!! happy new year, have a good time /close
MODiX
MODiX2y ago
Use the /close command to mark a forum thread as answered
Want results from more Discord servers?
Add your server
More Posts