Event vs EventHandler - c#

I read a lot of materials but I still did not understand, can someone explain me, please?
What do I know:
Declare an event:
public event MyEvent myEvent;
Vs.
declare EventHandler:
public EventHandler MyEventHandler;
While EventHandler is a keyword in .NET:
public delegate void EventHandler (Send object, EventArgs e);
So, EventHandler is a delegate and not an event, since it is not used in the keyword 'event'?
And when should I use 'Event' and when 'EventHandler'?

Ah, the event vs. delegate question. I remember having that question as well...
So, suppose you're making a class called "Cat" and you want to let people know when your cat is hungry. You could do that in one of two ways: by exposing a delegate on the Cat class or by exposing an event.
You can think of a delegate as a pointer to a function (or method). So let's say there's a class called "Person" that has a method called FeedCat(Cat cat).
The delegate way
If your cat is exposing a delegate called HungryDelegate, the person can point the delegate to their FeedCat method, so that when the cat is hungry, it has a way to call the FeedCat method on the person.
The problem here is, only one person can feed the cat. Suppose you want multiple people to be able to feed the cat. People can be busy doing other things, so it's important for the cat to be able to tell multiple people that it's hungry. That way, people get notified of this, and they can check up on the cat when they have a chance, see if someone already fed the cat, and feed it if not.
Events to the rescue:
An event is basically a list of delegates (of a certain type). If you expose a Hungry event on your "Cat" class, multiple people can ADD pointers (delegates) to their FeedCat methods.
They can also remove the pointers (delegates) to their FeedCat methods if they like. Let's say a person moved out, and their sister is now taking care of the cat. The person can remove their delegate for their own FeedCat function from the cat, so that they no longer get notified that the darn cat is hungry.
Events vs. multicast delegates?
Technically, in order to be able to provide multiple delegates, you could use the so called MultiCastDelegates instead of events. They are composite delegates (a linked list or delegates). The problem there is, everyone can mess with them from the outside. An evil person could remove everyone else's "FeedCat" delegates, and the poor cat would starve (or would have to learn to hunt).
The important thing when using events is that the person cannot see other people's delegates that are added to the event, and it can't remove them or interact with them (in principle).

Exposing a (public) field
public EventHandler MyEventHandler;
is a bad practice: one can easily ruin the code with a small typo:
MyClass demo = new MyClass();
demo.MyEventHandler += MyMethod;
...
// Can you see the error? = instead of correct += ?
// MyMethod will not be called since this assignment
demo.MyEventHandler = MyReaction;
That's why you should use event which has been specially desinged for this
public event EventHandler MyEventHandler;
if we try the previous demo we'll get compile time error:
MyClass demo = new MyClass();
...
demo.MyEventHandler = MyReaction; // <- doesn't compile, insist on +=
In very rare cases you may want explicit delegate-based fields, but these field should be concealed, say, be private, not public:
// We don't expose the field
private EventHandler m_MyEventHandler;
// ... But event:
public event EventHandler MyEventHandler {
add {
//TODO: extra logic on += operation
m_MyEventHandler += value;
}
remove {
//TODO: extra logic on -= operation
m_MyEventHandler -= value;
}
}

DELEGATES, EVENTS(EVENT HANDLERS/EVENT LISTENERS), CONCEPTS(MULTICASTING/BROADCASTING), ACTION & FUNC
This will be a long one but its the simplest explanation, the problem this is such a nuisance of a topic is because people are just using different words to explain the same thing
First of all, you should know a few things
DELEGATES: It's nothing but a list of methods, why create a list? because when your code is being executed, that list is taken and every method there is executed one by one, just don't listen to textbook definitions take this and you will be all right
also called :
a pointer to a function
a wrapper for a method that can send and receive methods just like a variable
to create a delegate you go
[[access modifier] delegate [return type] [delegate name]([parameters])]
example: public delegate int demo(int a);
now to execute all these methods stored in a list called delegate, you go
1. demo.invoke(a);
2. demo(a); ..... both are valid
using the dot and explicitly saying invoke shines in async programming where you use beginInvoke, but that is out of the scope of this topic
there is one more thing called "Creating an object of the delegate/instantiate Delegate" which is pretty much as it sounds but just to avoid confusion it goes like (for the above example )
example : demo del = new demo(); (or) Public demo del = null;
to add any method to the list called delegate you go += and you also need to remove it once the "requirements of the methods are met" you go -=
(requirements of the methods are met mean you no longer need the method to be active or aka "listening") if you don't remove it, it could cause a "memory leak" meaning your computers ram will be eaten alive, technically allocated memory will not be released
example: say there is a method
public int calculate (int c)
to add this method to delegate you go
1. del = calculate;
2. del += calculate; .... all are valid
to remove
del -= calculate
first of all notice the similarities between the delegate and the method, the return type(output) and the input/parameters are the same, and that is a rule you just cannot add any random or a bunch of methods in a delegate it needs to follow the input-output rule
now why are there 2 different ways to do one thing, the only thing different is the assignment operators (+, =), this introduces a new topic called
EVENTS
which is nothing but a constrained version of a Delegate, It's still a List of methods don't confuse when people explain these terminologies, they change the name, so stick with this to understand
what is the constraint? you cannot do this del = calculate;
what's the harm in it, say a bunch of methods are added to the Delegate(List), you do that šŸ‘† all are wiped out and only a single method "calculate" remains, so to prevent that Events are used,
Event Syntax
Public Event demo del = null;
One more thing you cannot do with events is invoke the delegate directly like demo.invoke since its public it can be accessed and invoked but with events, it can't
now you just add the methods to the event (a special type of delegate)
when to use an event vs a delegate, depends on your situation but pragmatically events are popular
few more keywords
MULTICASTING: nothing but adding more than one method to a delegate
BROADCASTING: adding more than one method to an event
PUBLISHER: the one that executes the method (term used in broadcasting), only a single entity
SUBSCRIBER: The methods that are being executed, can be multiple
LISTENER: the same thing as a subscriber but the term is used in multicasting
EVENT HANDLER: same thing as a subscriber/event listener so what the difference? it's basically the same thing, some say an eventlistener detect for the event to occur and the event handler "handles" or execute the code, ITS THE SAME THING PRACTICALLY!
action and func are just delegates that have been created and instantiated so 2 lines of code in a word, the difference is just in return types
ACTION: does not return anything while taking 0 or more than 1 input
FUNC: returns one thing and takes in parameters
if you don't do good with reading here is the best video on this topic
https://www.youtube.com/playlist?list=PLFt_AvWsXl0dliMtpZC8Qd_ru26785Ih_

Related

struggling in understanding terms in the Delegate world

I'm new to C#, I'm very confused with the terms used like 'listener', 'caller', 'callback', 'EventHandler', let's say we have the following code below:
public class Car
{
public delegate void CarEngineHandler();
public CarEngineHandler listOfHandlers;
public void Accelerate(int delta)
{
if (delta > 80)
listOfHandlers(); // not checking null for simplicity
}
}
class Program
{
static void Main(string[] args)
{
Car myCar = new Car();
myCar.listOfHandlers = new Car.CarEngineHandler(CallWhenExploded);
myCar.Accelerate(120);
}
static void CallWhenExploded()
{
Console.WriteLine("Sorry, this car is dead...");
}
}
so in this scenario:
Who is the caller?
Who is the listener? listen to what?
Who is the callback?
Who is the EventHandler?
and my answer is:
The caller is myCar
not sure
The callback is CallWhenExploded() static function
EventHandler is listOfHandlers
am I correct? I really don't know who is the listener and listen to what.
Hopefully you understand that an variable of type string is like a bucket that holds a string of characters, and you can look at them individually, pass them round as a collection etc. It's quite an easy thing to visualize, this variable being a container that stores data, because we store data all the time in the real world; pieces of paper in a box/file etc
Delegates are like variables for methods - and this is a much harder concept to understand, that we can pass a method round as though it were just like data, and we can get the computer to run the method.. but that's what a delegate is. When you declare a delegate, it's like when you declare your own class:
delegate void SomeMethod(); //specify a delegate
class Person{ //specify a class
string FirstName;
string LastName;
}
Just like when you make a class, you're giving yourself the ability to create an instance of that class, when you declare a delegate you're giving yourself the ability to create an instance of that delegate. Your class instance refers to data, like here the first and last name of the person. A delegate instance refers to a method rather than referring to data. You can make one class instance that refers to "John" and "Smith". You can make a delegate instance that refers to Method1(). You can make another class instance that refers to "Bill" "Jones". You can make another delegate instance that refers to Method2().
You can associate any method with your delegate instance, so long as the method has a signature that is equal to the delegate. That delegate above will accept a reference to any method that takes no parameters and returns void. If you've got one or more of these kind of methods you can attach them to an instance of the delegate, pass the delegate instance like a variable, and the thing you've passed the delegate to can call the methods without needing to know what the method name is or anything about it.
Why would we want to do this? One major use of delegates is in event handling. Microsoft created UI controls that are capable of doing things - buttons you can click on. You'll want your button to do something when it's clicked, but everyone in the world will want their button to do something different when it's clicked, so Microsoft can't write the code for that. They can however say that they will make a button that takes a delegate (a method passed like a variable) and the button promises to call the method when it is clicked. You supply the code that does what you want, as a delegate, to the button. Your method has to have a certain signature (arguments) because the button wants to pass your method some data that may be helpful to you; perhaps the location of the mouse when the clock occurred, or the number of times it was clicked. UI components have hundreds of different kinds of events, they all run on delegates
Another good example of delegates is in the old style of async programming when we had Begin/End pairs of methods, calling Begin would typically start a new thread off doing something and we would have to supply a method (our method) to it that, when Microsoft's Begin method had finished doing something it would call our method to let us know it was done. Typically then our code would call End, passing in some reference our method had been given, and we'd get the result. Sending a request to a server would take some time, for example, so we'd Begin it, go do some other things, and when the response was ready we would be notified by our delegate being called and we would process the result
So, get used to the notion that a delegate is just a way or referring to a method, you pass it around, what you pass it to can run it and provide data to it without having a clue what it does. In terminology it is also referred to as a callback - the thing that will be called when the foreign method is done with its work, though it's a fairly loose term - it might be used to refer to either your method that does the work, or the instance of a delegate pointing to your method, the thing that is passed in. Effectively they're equivalent dependi on the context of the conversation
A delegate itself is more like a collection/array - you can attach multiple methods to it and when the delegate is called they will all run, though not in any defined order. In your example you assigned just one to it but it could be multiple:
SomeMethod delegs = null;
delegs += new SomeMethod(MyMethod1);
delegs += new SomeMethod(MyMethod2);
Invoking that delegate will cause both MyMethod1 and MyMethod2 to be run, possibly in 2,1 order
Events are delegates too, but they're a slightly special case, touched on above with the button click handler. When a delegate is specified with the event keyword it can only be invoked inside the class that declared the delegate variable. UI controls use this to ensure that only they can run the delegate; you can't reach into a button and force run its clock handlers yourself because the delegate list that handles a click is declared as an event. If you want to programmatically cause a button to fire its event handler list you normally have to subclass it so your code becomes operationally "inside" the button code
Listener as a phrase is more often associated with events but it's reasonably synonymous with callback and eventhandler - when you add a listener to an event, you're saying that you're writing code that will handle the occurrence of the event, your code (as a delegate/event handler) that acts when the event occurs. It doesn't "listen" per se; it just hangs around and gets kicked into action when the thing raising the event invokes the list of delegates/eventhandlers associated with the event.
As an aside, because delegate instances represent a variable that points to a method, i.e. they point to an action, your naming of the instances should be a verb, not a noun. You called yours listOfHandlers but it would have been more helpful to your understanding to call the delegate instance after the event/action that is occurring. The use case you were applying was one of overrevving so perhaps you should name it CarEngineOverRevving. You could have another for when the temperature exceeds. If both these delegates has the same signature (you want people who will handle these events to do so via a method with no arguments) then you can reuse the same delegate for the different events:
public void delegate CarEngineProblemHandler();
public CarEngineProblemHandler CarEngineOverRevving = null;
public CarEngineProblemHandler CarEngineOverheating = null;
The delegate is your way of declaring what you want the methods provided to you, that you will call, to look like. The list of named problems is what you are declaring other people can provide some handling for. I could decide to not give you a handler for overrevving because I will never do it, but overheating might happen anyway so I'll certainly give you a handler/listener/delegate/callback to call of it ever happens
You should be able to answer those questions when you understand 'broadcaster/subscriber' pattern used by delegates. 'broadcaster' holds the delegate instance and decides when to call target methods in its 'invocation list'. These target methods are the 'subscribers' and they can decide when to stop or start 'listening' by calling '-=' or '+=' on broadcaster's delegate field.
public class Car
{
// This is the 'delegate type'
// ā€˜Delegate typeā€™ is what is responsible for defining the method such as its signature
// which include return type and parameters
// In this ā€˜Delegate typeā€™ named:'CarEngineHandler', the return type is 'void' and there are no parameters
public delegate void CarEngineHandler();
//this is the ā€˜Delegate instanceā€™
//ā€˜Delegate instanceā€™ is responsible for holding the reference to the actual methods
//that adheres to the delegate type.
//Delegate instance can be used to then ā€˜invokeā€™ that method whenever needed.
public CarEngineHandler listOfHandlers;
public void Accelerate(int delta)
{
if (delta > 80)
//this is where you use the 'Delegate instance' to ā€˜invokeā€™ the methods
// You can also you use: listOfHandlers.Invoke();
// which is same as calling 'listOfHandlers();'
// When delegate instance is invoked, all its actions in its invocation list are executed in order
//In this example it will first dispaly: "Sorry, this car is dead..."
// then display: "Calling, emergency..."
listOfHandlers(); // not checking null for simplicity
}
}
class Program
{
static void Main(string[] args)
{
Car myCar = new Car();
//This is where you add to the 'delegate instance', the 'target method's' that matches delegate signature
//A 'delegate instance' can contain more than one action. This list of actions is called the ā€œinvocation listā€.
//You can also add multiple methods to invocation list like this: myCar.listOfHandlers += CallWhenExploded;
myCar.listOfHandlers = new Car.CarEngineHandler(CallWhenExploded);
// For example you can add another target method like this:
myCar.listOfHandlers += CallEmergencyService;
// you get details about the 'target methods' attached to the ā€œinvocation listā€ like this:
var listOfTargets = myCar.listOfHandlers.GetInvocationList();
Console.WriteLine(listOfTargets[0].Method.Name);
myCar.Accelerate(120);
}
static void CallWhenExploded()
{
Console.WriteLine("Sorry, this car is dead...");
}
static void CallEmergencyService()
{
Console.WriteLine("Calling, emergency...");
}
}

Why can't events be invoked or their invocation list set from outside of the declaring class

Interview question: Why can't events be invoked and their invocation list set from outside of the declaring class?
I found explanation to the first part of the question in this post Events Invocation
I assume the answer for the second part lies with security.
Are there any other reasons considerations?
A keyword your interviewer may be looking for is encapsulation.
Events are only supposed to expose subscribe and unsubscribe operations to potential subscribers. Invocation is really the responsibility of the class that exposes the event.
Also keep in mind that public event EventHandler FooBar; is a short form of the following syntax
private EventHandler _fooBar;
public event EventHandler FooBar
{
add
{
_fooBar = (EventHandler)Delegate.Combine(_fooBar, value);
}
remove
{
_fooBar = (EventHandler)Delegate.Remove(_fooBar, value);
}
}
See Event Accessors
Because the class is the owner of those events.
We say that example in OOPS should be taken from real world examples. So if you are an entity and you do an event of let's say raising your hand, would you like to keep the authority of raising your hand with yourself or give to someone else?
But there is a catch
A C# short-format event declaration direct the compiler to declare a field of delegate type which, for unfortunate historical reasons, is given the same name as the event. Because the field declaration is generated by the compiler, rather than being part of user code, there is no means by which its scope can be set to anything other than private. If you wish to have the delegate or delegates associated with an event be accessible to child classes, then it's necessary to use something like the form shown by Brandon Cuff (though perhaps guarded with an Interlocked.CompareExchange).

Why do Events need Delegates? Why do we even Need Events?

I've been confused over the past weeks now about events. I understand how delegates work, not how it works in detail but enough to know that
delegate datatype is a single cast delegate.
delegate void is a multicast delegate - a list of references to methods.
I know a delegate type compiles to a class, but unfortunately I am still not sure how the method is referenced. For example
delegate void TestDelegate();
TestDelegate testDelegate = new TestDelegate(myObject.SomeMethod) ;
Question 1: I think myObject is the target, and SomeMethod is the method to reference, but I'm only passing one input.
So is myObject.SomeMethod compiled to a string and is the string split by the period? Ridiculous I know.
Question 2:
When you add to a multicast delegate
multicastdelegate+=newmethodtobereference
multicastdelegate() ;
Every method in the invocation list is called or notified?
If that's true, why the hell do I need events or the event keyword? Is it simply to tell the developers that Hey, this is acting as an event? Because I'm seriously confused, I just want to move on at this stage lol. This is a sample code I wrote to test it today whether I need event keyword or not.
using System;
namespace LambdasETs
{
public delegate void IsEvenNumberEventHandler(int numberThatIsEven);
public class IsEvenNumberFound
{
public IsEvenNumberEventHandler IsEvenNumberEvent;
private int number;
public void InputNumber(int n)
{
if(number %2 ==0)
{
if (IsEvenNumberEvent != null)
{
IsEvenNumberEvent(n);
}
}
}
public static void Main()
{
IsEvenNumberFound isEvenNumberFound = new IsEvenNumberFound();
isEvenNumberFound.IsEvenNumberEvent += IsEvenNumberAction;
isEvenNumberFound.InputNumber(10);
Console.ReadLine();
}
public static void IsEvenNumberAction(int number)
{
Console.WriteLine("{0} is an even number!", number);
}
}
}
Adding the event keyword to the field public IsEvenNumberEventHandler IsEvenNumberEvent; has no difference.
Please can some explain so that a noob can understand thanks.
An event is an accessor for a delegate, just like a property is an accessor for a field. With much the same goals, it prevents other code from messing with the delegate object. Like setting it null when a bunch of code you don't know about have subscribed a callback. An event restricts access to only adding and removing event handlers with the += and -= operators, external code cannot access the private delegate object at all.
And to customize the subscription with the add and remove accessors. You don't often do so because you are typically happy with the default accessors generated by the compiler. Including a hidden backing field that stores a delegate. But it is not uncommon in the framework code for example. Like all the event handlers for the many events that System.Windows.Forms.Control supports, they are all stored in a single EventHandlerList. Or the WPF equivalent, EventHandlersStore.
but enough to know that delegate datatype is a single cast delegate. delegate void is a multicast delegate - a list of references to methods.
Not true. All "normal" delegates are multicast, even if they have a non void return type.
Question 1: I think myObject is the target, and SomeMethod is the method to reference, but I'm only passing one input. So is myObject.SomeMethod compiled to a string and is the string split by the period? Ridiculous I know.
No, myObject.SomeMethod is a method group. This way of delegate instance creation involves a bit of compiler magic.
multicastdelegate+=newmethodtobereference
If multicastdelegate is a normal delegate variable, this is equivalent to multicastdelegate = multicastdelegate + newmethodtobereference i.e. it creates a new delegate that calls several methods, and assigns it to multicastdelegate.
Now to your main question: What's the purpose of events?
Events have delegate types. They behave similarly to properties. Their purpose is encapsulation, in particular they only allow consumers to subscribe(+=) and unsubscribe(-=) but not to read the value of the event.
Properties are a combination of two methods: get and set.
Events are a combination of two public methods subscribe and unsubscribe, and in the case of a field-like event also something similar to a private getter.

Two questions regarding events

I would like to know:
Subscriber is a name for class that subscribes for the event or also for the method that is handling the event? I mean, does it make sense to say "subscribe method to event"?
On MSDN it says that event delegate should have exactly 2 arguments. Not sure what it means as I often create events with my custom delegate that has e.g. none or one argument.
1) Yes, it definitely makes sense to talk about subscribing a method to an event. You can actually think of there being three entities involved:
The subscribing code which is actually performing the subscription itself
The event publisher
The handler which is being subscribed; this is often - but not always - code in the same class as the subscribing code
2) You certainly can create events using delegates with any number of parameters. The convention is that delegates used in events have two parameters: a "sender" and an "argument" derived from EventArgs. For example, this means that you can subscribe a handler from a method with a signature of void Foo(object sender, EventArgs e) to any event following the convention.
A subscriber is a method that is added as an event handler.
Standard practice is to use the EventHandler<T> delegate for events; this has two arguments.
However, you can create your own events with any number of arguments.
I'll concentrate on the second point. As Jon pointed out, you can use your own delegates for events. But you rarely should. Even if you don't care about conventions, look at it this way: whenever you use your own events with custom delegates, you have the following code besides the event field itself:
Your custom delegate
Event handlers (methods with matching signature) - sometimes a lot of them
Event invocation points (where you need to pass all the parameters)- sometimes a lot of them
I also tend to create the InvokeMyEvent methods that do the nullity checking and other stuff that needs to be done
You have to change all of these if you decide to add or remove a parameter or change a parameter type.
Now, if you create your own class that inherits EventArgs or use the EventArgs<T>, you have:
Your CustomEventArgs class
Event handlers
Event invocation points
InvokeMyEvent methods.
Whenever you decide to change the event args you have to change only your custom args class and some of the event invocation points. "Some", because you can provide suitable default values for fields of your args class and only provide the values when you need it.
Most of good/bad practice talks are focused on one thing - ease of change. Changes always happen. The fewer things you have to alter when they do, the better. Design has a lot of iterations and the odds are that you'll have to change your interfaces and types a lot. You don't want to change tens of signatures whenever you decide that you don't need the parameter anymore. So use the EventArgs or EventArgs<T> and save yourself some headache.
Another minor point is that you'll probably want to declare some methods that take care of raising the events, like this:
public static public void FireEvent<T>(this EventHandler handler, object sender, EventArgs<T> e)
where T : EventArgs
{
if (handler != null)
handler(sender, e);
}
If all your events are EventHandler-based, you can use one all-purpose method for things like that. If not, then you'll eventually have tens of them.

Understanding events and event handlers in C#

I understand the purpose of events, especially within the context of creating user interfaces. I think this is the prototype for creating an event:
public void EventName(object sender, EventArgs e);
What do event handlers do, why are they needed, and how do I to create one?
To understand event handlers, you need to understand delegates. In C#, you can think of a delegate as a pointer (or a reference) to a method. This is useful because the pointer can be passed around as a value.
The central concept of a delegate is its signature, or shape. That is (1) the return type and (2) the input arguments. For example, if we create a delegate void MyDelegate(object sender, EventArgs e), it can only point to methods which return void, and take an object and EventArgs. Kind of like a square hole and a square peg. So we say these methods have the same signature, or shape, as the delegate.
So knowing how to create a reference to a method, let's think about the purpose of events: we want to cause some code to be executed when something happens elsewhere in the system - or "handle the event". To do this, we create specific methods for the code we want to be executed. The glue between the event and the methods to be executed are the delegates. The event must internally store a "list" of pointers to the methods to call when the event is raised.* Of course, to be able to call a method, we need to know what arguments to pass to it! We use the delegate as the "contract" between the event and all the specific methods that will be called.
So the default EventHandler (and many like it) represents a specific shape of method (again, void/object-EventArgs). When you declare an event, you are saying which shape of method (EventHandler) that event will invoke, by specifying a delegate:
//This delegate can be used to point to methods
//which return void and take a string.
public delegate void MyEventHandler(string foo);
//This event can cause any method which conforms
//to MyEventHandler to be called.
public event MyEventHandler SomethingHappened;
//Here is some code I want to be executed
//when SomethingHappened fires.
void HandleSomethingHappened(string foo)
{
//Do some stuff
}
//I am creating a delegate (pointer) to HandleSomethingHappened
//and adding it to SomethingHappened's list of "Event Handlers".
myObj.SomethingHappened += new MyEventHandler(HandleSomethingHappened);
//To raise the event within a method.
SomethingHappened("bar");
(*This is the key to events in .NET and peels away the "magic" - an event is really, under the covers, just a list of methods of the same "shape". The list is stored where the event lives. When the event is "raised", it's really just "go through this list of methods and call each one, using these values as the parameters". Assigning an event handler is just a prettier, easier way of adding your method to this list of methods to be called).
C# knows two terms, delegate and event. Let's start with the first one.
Delegate
A delegate is a reference to a method. Just like you can create a reference to an instance:
MyClass instance = myFactory.GetInstance();
You can use a delegate to create an reference to a method:
Action myMethod = myFactory.GetInstance;
Now that you have this reference to a method, you can call the method via the reference:
MyClass instance = myMethod();
But why would you? You can also just call myFactory.GetInstance() directly. In this case you can. However, there are many cases to think about where you don't want the rest of the application to have knowledge of myFactory or to call myFactory.GetInstance() directly.
An obvious one is if you want to be able to replace myFactory.GetInstance() into myOfflineFakeFactory.GetInstance() from one central place (aka factory method pattern).
Factory method pattern
So, if you have a TheOtherClass class and it needs to use the myFactory.GetInstance(), this is how the code will look like without delegates (you'll need to let TheOtherClass know about the type of your myFactory):
TheOtherClass toc;
//...
toc.SetFactory(myFactory);
class TheOtherClass
{
public void SetFactory(MyFactory factory)
{
// set here
}
}
If you'd use delegates, you don't have to expose the type of my factory:
TheOtherClass toc;
//...
Action factoryMethod = myFactory.GetInstance;
toc.SetFactoryMethod(factoryMethod);
class TheOtherClass
{
public void SetFactoryMethod(Action factoryMethod)
{
// set here
}
}
Thus, you can give a delegate to some other class to use, without exposing your type to them. The only thing you're exposing is the signature of your method (how many parameters you have and such).
"Signature of my method", where did I hear that before? O yes, interfaces!!! interfaces describe the signature of a whole class. Think of delegates as describing the signature of only one method!
Another large difference between an interface and a delegate is that when you're writing your class, you don't have to say to C# "this method implements that type of delegate". With interfaces, you do need to say "this class implements that type of an interface".
Further, a delegate reference can (with some restrictions, see below) reference multiple methods (called MulticastDelegate). This means that when you call the delegate, multiple explicitly-attached methods will be executed. An object reference can always only reference to one object.
The restrictions for a MulticastDelegate are that the (method/delegate) signature should not have any return value (void) and the keywords out and ref is not used in the signature. Obviously, you can't call two methods that return a number and expect them to return the same number. Once the signature complies, the delegate is automatically a MulticastDelegate.
Event
Events are just properties (like the get;set; properties to instance fields) which expose subscription to the delegate from other objects. These properties, however, don't support get;set;. Instead, they support add; remove;
So you can have:
Action myField;
public event Action MyProperty
{
add { myField += value; }
remove { myField -= value; }
}
Usage in UI (WinForms,WPF,UWP So on)
So, now we know that a delegate is a reference to a method and that we can have an event to let the world know that they can give us their methods to be referenced from our delegate, and we are a UI button, then: we can ask anyone who is interested in whether I was clicked, to register their method with us (via the event we exposed). We can use all those methods that were given to us and reference them by our delegate. And then, we'll wait and wait.... until a user comes and clicks on that button, then we'll have enough reason to invoke the delegate. And because the delegate references all those methods given to us, all those methods will be invoked. We don't know what those methods do, nor we know which class implements those methods. All we do care about is that someone was interested in us being clicked, and gave us a reference to a method that complied with our desired signature.
Java
Languages like Java don't have delegates. They use interfaces instead. The way they do that is to ask anyone who is interested in 'us being clicked', to implement a certain interface (with a certain method we can call), then give us the whole instance that implements the interface. We keep a list of all objects implementing this interface and can call their 'certain method we can call' whenever we get clicked.
That is actually the declaration for an event handler - a method that will get called when an event is fired. To create an event, you'd write something like this:
public class Foo
{
public event EventHandler MyEvent;
}
And then you can subscribe to the event like this:
Foo foo = new Foo();
foo.MyEvent += new EventHandler(this.OnMyEvent);
With OnMyEvent() defined like this:
private void OnMyEvent(object sender, EventArgs e)
{
MessageBox.Show("MyEvent fired!");
}
Whenever Foo fires off MyEvent, then your OnMyEvent handler will be called.
You don't always have to use an instance of EventArgs as the second parameter. If you want to include additional information, you can use a class derived from EventArgs (EventArgs is the base by convention). For example, if you look at some of the events defined on Control in WinForms, or FrameworkElement in WPF, you can see examples of events that pass additional information to the event handlers.
Here is a code example which may help:
using System;
using System.Collections.Generic;
using System.Text;
namespace Event_Example
{
// First we have to define a delegate that acts as a signature for the
// function that is ultimately called when the event is triggered.
// You will notice that the second parameter is of MyEventArgs type.
// This object will contain information about the triggered event.
public delegate void MyEventHandler(object source, MyEventArgs e);
// This is a class which describes the event to the class that receives it.
// An EventArgs class must always derive from System.EventArgs.
public class MyEventArgs : EventArgs
{
private string EventInfo;
public MyEventArgs(string Text) {
EventInfo = Text;
}
public string GetInfo() {
return EventInfo;
}
}
// This next class is the one which contains an event and triggers it
// once an action is performed. For example, lets trigger this event
// once a variable is incremented over a particular value. Notice the
// event uses the MyEventHandler delegate to create a signature
// for the called function.
public class MyClass
{
public event MyEventHandler OnMaximum;
private int i;
private int Maximum = 10;
public int MyValue
{
get { return i; }
set
{
if(value <= Maximum) {
i = value;
}
else
{
// To make sure we only trigger the event if a handler is present
// we check the event to make sure it's not null.
if(OnMaximum != null) {
OnMaximum(this, new MyEventArgs("You've entered " +
value.ToString() +
", but the maximum is " +
Maximum.ToString()));
}
}
}
}
}
class Program
{
// This is the actual method that will be assigned to the event handler
// within the above class. This is where we perform an action once the
// event has been triggered.
static void MaximumReached(object source, MyEventArgs e) {
Console.WriteLine(e.GetInfo());
}
static void Main(string[] args) {
// Now lets test the event contained in the above class.
MyClass MyObject = new MyClass();
MyObject.OnMaximum += new MyEventHandler(MaximumReached);
for(int x = 0; x <= 15; x++) {
MyObject.MyValue = x;
}
Console.ReadLine();
}
}
}
Just to add to the existing great answers here - building on the code in the accepted one, which uses a delegate void MyEventHandler(string foo)...
Because the compiler knows the delegate type of the SomethingHappened event, this:
myObj.SomethingHappened += HandleSomethingHappened;
Is totally equivalent to:
myObj.SomethingHappened += new MyEventHandler(HandleSomethingHappened);
And handlers can also be unregistered with -= like this:
// -= removes the handler from the event's list of "listeners":
myObj.SomethingHappened -= HandleSomethingHappened;
For completeness' sake, raising the event can be done like this, only in the class that owns the event:
//Firing the event is done by simply providing the arguments to the event:
var handler = SomethingHappened; // thread-local copy of the event
if (handler != null) // the event is null if there are no listeners!
{
handler("Hi there!");
}
The thread-local copy of the handler is needed to make sure the invocation is thread-safe - otherwise a thread could go and unregister the last handler for the event immediately after we checked if it was null, and we would have a "fun" NullReferenceException there.
C# 6 introduced a nice short hand for this pattern. It uses the null propagation operator.
SomethingHappened?.Invoke("Hi there!");
My understanding of the events is;
Delegate:
A variable to hold reference to method / methods to be executed. This makes it possible to pass around methods like a variable.
Steps for creating and calling the event:
The event is an instance of a delegate
Since an event is an instance of a delegate, then we have to first define the delegate.
Assign the method / methods to be executed when the event is fired (Calling the delegate)
Fire the event (Call the delegate)
Example:
using System;
namespace test{
class MyTestApp{
//The Event Handler declaration
public delegate void EventHandler();
//The Event declaration
public event EventHandler MyHandler;
//The method to call
public void Hello(){
Console.WriteLine("Hello World of events!");
}
public static void Main(){
MyTestApp TestApp = new MyTestApp();
//Assign the method to be called when the event is fired
TestApp.MyHandler = new EventHandler(TestApp.Hello);
//Firing the event
if (TestApp.MyHandler != null){
TestApp.MyHandler();
}
}
}
}
//This delegate can be used to point to methods
//which return void and take a string.
public delegate void MyDelegate(string foo);
//This event can cause any method which conforms
//to MyEventHandler to be called.
public event MyDelegate MyEvent;
//Here is some code I want to be executed
//when SomethingHappened fires.
void MyEventHandler(string foo)
{
//Do some stuff
}
//I am creating a delegate (pointer) to HandleSomethingHappened
//and adding it to SomethingHappened's list of "Event Handlers".
myObj.MyEvent += new MyDelegate (MyEventHandler);
publisher: where the events happen. Publisher should specify which delegate the class is using and generate necessary arguments, pass those arguments and itself to the delegate.
subscriber: where the response happen. Subscriber should specify methods to respond to events. These methods should take the same type of arguments as the delegate. Subscriber then add this method to publisher's delegate.
Therefore, when the event happen in publisher, delegate will receive some event arguments (data, etc), but publisher has no idea what will happen with all these data. Subscribers can create methods in their own class to respond to events in publisher's class, so that subscribers can respond to publisher's events.
I recently made an example of how to use events in c#, and posted it on my blog. I tried to make it as clear as possible, with a very simple example. In case it might help anyone, here it is: http://www.konsfik.com/using-events-in-csharp/
It includes description and source code (with lots of comments), and it mainly focuses on a proper (template - like) usage of events and event handlers.
Some key points are:
Events are like "sub - types of delegates", only more constrained (in a good way). In fact an event's declaration always includes a delegate (EventHandlers are a type of delegate).
Event Handlers are specific types of delegates (you may think of them as a template), which force the user to create events which have a specific "signature". The signature is of the format: (object sender, EventArgs eventarguments).
You may create your own sub-class of EventArgs, in order to include any type of information the event needs to convey. It is not necessary to use EventHandlers when using events. You may completely skip them and use your own kind of delegate in their place.
One key difference between using events and delegates, is that events can only be invoked from within the class that they were declared in, even though they may be declared as public. This is a very important distinction, because it allows your events to be exposed so that they are "connected" to external methods, while at the same time they are protected from "external misuse".
Another thing to know about, in some cases, you have to use the Delegates/Events when you need a low level of coupling !
If you want to use a component in several place in application, you need to make a component with low level of coupling and the specific unconcerned LOGIC must be delegated OUTSIDE of your component ! This ensures that you have a decoupled system and a cleaner code.
In SOLID principle this is the "D", (Dependency inversion principle).
Also known as "IoC", Inversion of control.
You can make "IoC" with Events, Delegates and DI (Dependency Injection).
It's easy to access a method in a child class. But more difficult to access a method in a parent class from child. You have to pass the parent reference to the child ! (or use DI with Interface)
Delegates/Events allows us to communicate from the child to the parent without reference !
In this diagram above, I do not use Delegate/Event and the parent component B has to have a reference of the parent component A to execute the unconcerned business logic in method of A. (high level of coupling)
With this approach, I would have to put all the references of all components that use component B ! :(
In this diagram above, I use Delegate/Event and the component B doesn't have to known A. (low level of coupling)
And you can use your component B anywhere in your application !
I agree with KE50 except that I view the 'event' keyword as an alias for 'ActionCollection' since the event holds a collection of actions to be performed (ie. the delegate).
using System;
namespace test{
class MyTestApp{
//The Event Handler declaration
public delegate void EventAction();
//The Event Action Collection
//Equivalent to
// public List<EventAction> EventActions=new List<EventAction>();
//
public event EventAction EventActions;
//An Action
public void Hello(){
Console.WriteLine("Hello World of events!");
}
//Another Action
public void Goodbye(){
Console.WriteLine("Goodbye Cruel World of events!");
}
public static void Main(){
MyTestApp TestApp = new MyTestApp();
//Add actions to the collection
TestApp.EventActions += TestApp.Hello;
TestApp.EventActions += TestApp.Goodbye;
//Invoke all event actions
if (TestApp.EventActions!= null){
//this peculiar syntax hides the invoke
TestApp.EventActions();
//using the 'ActionCollection' idea:
// foreach(EventAction action in TestApp.EventActions)
// action.Invoke();
}
}
}
}
Great technical answers in the post! I have nothing technically to add to that.
One of the main reasons why new features appear in languages and software in general is marketing or company politics! :-) This must not be under estimated!
I think this applies to certain extend to delegates and events too! i find them useful and add value to the C# language, but on the other hand the Java language decided not to use them! they decided that whatever you are solving with delegates you can already solve with existing features of the language i.e. interfaces e.g.
Now around 2001 Microsoft released the .NET framework and the C# language as a competitor solution to Java, so it was good to have NEW FEATURES that Java doesn't have.
DELEGATES, EVENTS(EVENT HANDLERS/EVENT LISTENERS), CONCEPTS(MULTICASTING/BROADCASTING), ACTION & FUNC
This will be a long one but its the simplest explanation, the problem this is such a nuisance of a topic is because people are just using different words to explain the same thing
First of all, you should know a few things
DELEGATES: It's nothing but a list of methods, why create a list? because when your code is being executed, that list is taken and every method there is executed one by one, just don't listen to textbook definitions take this and you will be all right
also called :
a pointer to a function
a wrapper for a method that can send and receive methods just like a variable
to create a delegate you go
[[access modifier] delegate [return type] [delegate name]([parameters])]
example: public delegate int demo(int a);
now to execute all these methods stored in a list called delegate, you go
1. demo.invoke(a);
2. demo(a); ..... both are valid
using the dot and explicitly saying invoke shines in async programming where you use beginInvoke, but that is out of the scope of this topic
there is one more thing called "Creating an object of the delegate/instantiate Delegate" which is pretty much as it sounds but just to avoid confusion it goes like (for the above example )
example : demo del = new demo(); (or) Public demo del = null;
to add any method to the list called delegate you go += and you also need to remove it once the "requirements of the methods are met" you go -=
(requirements of the methods are met mean you no longer need the method to be active or aka "listening") if you don't remove it, it could cause a "memory leak" meaning your computers ram will be eaten alive, technically allocated memory will not be released
example: say there is a method
public int calculate (int c)
to add this method to delegate you go
1. del = calculate;
2. del += calculate; .... all are valid
to remove
del -= calculate
first of all notice the similarities between the delegate and the method, the return type(output) and the input/parameters are the same, and that is a rule you just cannot add any random or a bunch of methods in a delegate it needs to follow the input-output rule
now why are there 2 different ways to do one thing, the only thing different is the assignment operators (+, =), this introduces a new topic called
EVENTS
which is nothing but a constrained version of a Delegate, It's still a List of methods don't confuse when people explain these terminologies, they change the name, so stick with this to understand
what is the constraint? you cannot do this del = calculate;
what's the harm in it, say a bunch of methods are added to the Delegate(List), you do that šŸ‘† all are wiped out and only a single method "calculate" remains, so to prevent that Events are used,
Event Syntax
Public Event demo del = null;
One more thing you cannot do with events is invoke the delegate directly like demo.invoke since its public it can be accessed and invoked but with events, it can't
now you just add the methods to the event (a special type of delegate)
when to use an event vs a delegate, depends on your situation but pragmatically events are popular
few more keywords
MULTICASTING: nothing but adding more than one method to a delegate
BROADCASTING: adding more than one method to an event
PUBLISHER: the one that executes the method (term used in broadcasting), only a single entity
SUBSCRIBER: The methods that are being executed, can be multiple
LISTENER: the same thing as a subscriber but the term is used in multicasting
EVENT HANDLER: same thing as a subscriber/event listener so what the difference? it's basically the same thing, some say an eventlistener detect for the event to occur and the event handler "handles" or execute the code, ITS THE SAME THING PRACTICALLY!
action and func are just delegates that have been created and instantiated so 2 lines of code in a word, the difference is just in return types
ACTION: does not return anything while taking 0 or more than 1 input
FUNC: returns one thing and takes in parameters
if you don't do good with reading here is the best video on this topic
https://www.youtube.com/playlist?list=PLFt_AvWsXl0dliMtpZC8Qd_ru26785Ih_

Categories

Resources