Generic Interface with TDelegate as an event? - c#

I am trying to create this simple interface. I want it somehow to be able to fire an event.
This is what I have till now (doesn't compile, just my thoughts)
public interface IAsyncSearch<TTermType, TResultsEventType>
where TResultsEventType:delegate
{
event TResultsEventType SearchCompletedEvent;
void SearchAsync(TTermType term);
}
Is something similar even possible? I know that a type is expected in the where statement.

Try this
public interface IAsyncSearch<TData, TArgs>
{
event EventHandler<SpecialDataEventArgs<TArgs>> SearchCompletedEvent;
void SearchAsync(TData term);
}
public class SpecialDataEventArgs<T> : EventArgs
{
public SpecialDataEventArgs(T data)
{
Data = data;
}
public T Data { get; private set; }
}

All event types ought to derive from EventHandler<>, the standard .NET event handler type. Helps anybody that reads your code recognize it quickly. And even more appropriate here, it readily solves your problem:
public interface IAsyncSearch<TTermType, TResultsArgType>
where TResultArgType : EventArgs
{
event EventHandler<TResultsArgType> SearchCompletedEvent;
void SearchAsync(TTermType term);
}

Events work only with delegate types. And there is no way to constrain type parameter to be a delegate in C#. Because of that, I don't think what you want is possible in C#.
According to Jon Skeet, it actually may be possible to do this in CIL, so maybe if you wrote that type in CIL, you could be able to use it from C# the way you want.
EDIT: You can create such type in CIL, but it seems you can't use it property from C#. It seems you can't implement it. And calling the event methods using += doesn't work either. But calling them using the add_SearchCompletedEvent does work.

Related

Delegate example what's the point

Like many other posts I've found on SO, I'm trying to get my head around delegates. Hopefully this example is not classed a duplicate because I am asking a specific question about a particular example.
public delegate void HelloFunctionDelegate(string message);
public class Delegate
{
static void Main()
{
HelloFunctionDelegate del = new HelloFunctionDelegate(GoodNight); // delegate will point to the GoodNight method
del("Hello"); // invoke the delegate
}
public static void GoodMorning(string strMessage)
{
Console.WriteLine(strMessage + " and good morning!");
Console.ReadKey();
}
public static void GoodNight(string strMessage)
{
Console.WriteLine(strMessage + " and good night!");
Console.ReadKey();
}
}
So in my example I understand that my delegate is a reference to any function that matches its signature and if I pass in GoodMorning I will see:
Hello and good morning!
and if I pass in GoodNight I will see: Hello and good night!
So its kind of like going through a middle man...
I don't understand is what's the point, why wouldn't I just directly call my GoodMorning / GoodNight methods as and when I need to use them?
Maybe there are better examples for when a delegate is useful, but in this example, why don't I just bypass the middle man?
Since you are asking concretely about this example and not in general: There is no point to doing that in this particular piece of code. It teaches you the mechanics of delegates but it does not teach you the point of using them.
In short, the point is that some piece of code can take a reference to a method without knowing what method it will actually receive. It can later call that delegate at will. That enables more abstractions than otherwise possible.
Consider you have the following delegate:
public delegate void CarEvent(Car car);
And then you have an implementation like the following:
public class Car : DataRecord
{
// An event to execute when the record is deleted
public CarEvent OnDelete { get; set; }
public void Delete()
{
this.DeleteRecord(); // Deletes this record from ex. the database
if (OnDelete)
{
OnDelete(this); // Executes the event
}
}
}
By using a delegate you can subscribe different methods to the OnDelete allowing you to do different things when the record is deleted.
Ex. you can make it so when the record is deleted it's deleted from a "ListView" that holds it.
public class CarList : ListView
{
public CarList()
: base()
{
foreach (var car in CarRecords.LoadCars())
{
var listViewItem = new ListViewItem(car);
car.OnDelete = this.DeleteCarFromList;
this.Items.Add(listViewItem);
}
}
private void DeleteCarFromList(Car deletedCar)
{
this.Items.Remove(deletedCar);
}
}
Of course the above is a rough example and there is a lot more things and different kind of situations where you can use delegates and most notably if you want to use them for events you should consider implementing them using the event keyword. - https://msdn.microsoft.com/en-us/library/awbftdfh.aspx
All in all you want to use delegates when the behavior may differ depending on the overall implementation of something. Like you might want to do one thing in one situation and something else in another situation, but they should both over-all do the same thing.
If you do not need different behaviors based on implementation then there's no need to use delegates. You'd always want to call a method directly if possible.
I hope this explained it okay.

Are there compelling reasons to use EventHandler<T> delegate instead of just Action<T> when declaring events?

When I declare an event, I've been using the Action delegate or Action<T, ...> delegate if the event handler has parameters. I recently noticed the existence of the EventHandler delegate, which requires a type param that inherits EventArgs. The latter method requires that I create an additional class that exists only to encapsulate whatever parameters are passed with the event, which seems unnecessary, unless I'm missing something.
So, what are the reasons for using the EventArgs delegate when declaring an event? What does it buy me?
It buys you the ability to return event arguments, that's all. If you have no need for that, then maybe you don't need an EventHandler delegate.
From a larger perspective, EventArgs is the "socially acceptable" way of getting data from one place to another using events. You can create custom delegates to do this, of course, but EventArgs has tooling support in Visual Studio, etc.
It provides you with an extensibility point for changing your event in the future.
Let's say I define a class Car:
public class Car {
String Make { get; set; }
String Model { get; set; }
int Year { get; set; }
}
and an event CarBuilt:
public event Action<Car> CarBuilt;
That's fine. But then, what if I want the event to later include the person who built the car? Using an action, I need to either change the event signature or add that information to the Car class (where it really doesnt belong).
If I define it this way instead:
public class CarBuiltEventArgs : EventArgs {
public Car TheCar { get; set; }
}
public event EventHandler<CarBuiltEventArgs> CarBuilt;
Then I can add the BuiltBy property to the CarBuiltEventArgs class and I'm all set.
public class CarBuiltEventArgs : EventArgs {
public Car TheCar { get; set; }
public String BuiltBy { get; set; }
}
You indicated you use Action if arguments are needed. Comparing the two ask yourself what would be required if next year your requirements change and you need a new parameter passed in that event? Do you change lots of code or just one class that inherits EventArgs?
The biggest reason for using EventHandler<T> is probably that delegates of different types--even those types use the same method signature--are not interchangeable. If one event uses an EventHandler<fnordEventArgs> and another uses an Action<Object, fnordEventArgs>, the same methods could be subscribed to both events, but delegates created for one event could not be used with the other. Normally, this would be no big deal, since the statement like FirstEvent += methodName would translate into FirstEvent += new EventHandler<fnordEventArgs>(methodName), and SecondEvent += methodName would translate into FirstEvent += new Action<Object, fnordEventArgs>(methodName). In some cases, however, it is necessary for an event subscriber to store the delegate used to subscribe. For the subscriber to store the delegate, it must know its type--correctly. Consistently using EventHandler<T> as the delegate for event handling methods of the form void EventHandler(Object sender, T args) makes it must easier to create the right delegate type.

Embedded Mono: How do you raise an event in C++?

I'm working on an application that's embedding Mono, and I'd like to raise an event from the C++ layer into the C# layer. Here's what I have:
void* itr(NULL);
MonoEvent* monoEvent;
while(monoEvent= mono_class_get_events(klass, &itr))
{
if(0 == strcmp(eventName, mono_event_get_name(monoEvent)))
raiseMethod = mono_event_get_raise_method(monoEvent);
}
However, raiseMethod always comes back as NULL. Looking at the structure of the MonoEvent, it looks like the add and remove methods were populated, but not the raise? Is there something special I have to do to get this to work?
EDIT: If it matters, here's the (basic) form of the delegate, class, and events I'm using in the C# layer.
public delegate void MyHandler(uint id);
public class SimpleComponent : NativeComponent
{
public event MyHandler OnEnter;
public event MyHandler OnExit;
}
May the event be defined in parent class? If so you need to traverse up the class hierarchy with something like the following:
MonoEvent* monoEvent;
while (klass)
{
void* itr = NULL;
while(monoEvent= mono_class_get_events(klass, &itr))
{
if(0 == strcmp(eventName, mono_event_get_name(monoEvent)))
raiseMethod = mono_event_get_raise_method(monoEvent);
}
klass = mono_class_get_parent(klass);
}
EDIT after comment and re-reading question:
It is normal that the raise method for event is NULL.
This method usually returns null for events declared with the C# event keyword or the Visual Basic Event keyword. This is because the C# and Visual Basic compilers do not generate such a method by default.
(source)
I am afraid it may be hard to fire an event of a class. Because it is actually breaking the concept of events in .NET - which says that the class itself can only fire its own Event. Actually, even from C# it is hard to raise the event of other class.
Conceptually, events are pair of add_handler and remove_handler methods where you specify delegates to be called when event's circumstances occur. It is up to class how it implements events. Technically, it is just a private delegate field, AFAIK.
You may try to locate it.
I am not sure if it is a proper approach, but one of the answers in How do I raise an event via reflection in .NET/C#? describes how to raise event using reflection. You might attempt to convert it into mono_class / mono_field calls, etc.
Krizz's answer is the most complete. This is how I fixed my code to work how I would "expect".
I changed the C# side to:
public delegate void MyHandler(uint aEntityId);
public class SimpleComponent: NativeComponent
{
public event MyHandler OnEnter;
public event MyHandler OnExit;
protected void CallOnEnter(uint aEntityId)
{
if (OnEnter != null)
OnEnter(aEntityId);
}
protected void CallOnExit(uint aEntityId)
{
if (OnExit!= null)
OnExit(aEntityId);
}
}
Then grabbed the mono method with
raiseMethod = mono_class_get_method_from_name(klass, "CallOnEnter", 1);

C# Language Design: explicit interface implementation of an event

Small question about C# language design :))
If I had an interface like this:
interface IFoo {
int Value { get; set; }
}
It's possible to explicitly implement such interface using C# 3.0 auto-implemented properties:
sealed class Foo : IFoo {
int IFoo.Value { get; set; }
}
But if I had an event in the interface:
interface IFoo {
event EventHandler Event;
}
And trying to explicitly implement it using field-like event:
sealed class Foo : IFoo {
event EventHandler IFoo.Event;
}
I will get the following compiler error:
error CS0071: An explicit interface implementation of an event must use event accessor syntax
I think that field-like events is the some kind of dualism for auto-implemented properties.
So my question is: what is the design reason for such restriction done?
Interesting question. I did some poking around the language notes archive and I discovered that this decision was made on the 13th of October, 1999, but the notes do not give a justification for the decision.
Off the top of my head I don't see any theoretical or practical reason why we could not have field-like explicitly implemented events. Nor do I see any reason why we particularly need to. This may have to remain one of the mysteries of the unknown.
I guess it might have to do with the fact that you can't call an explicit interface implementation from other members of the class:
public interface I
{
void DoIt();
}
public class C : I
{
public C()
{
DoIt(); // error CS0103: The name 'DoIt' does not exist in the current context
}
void I.DoIt() { }
}
Note that you can call the method by upcasting to the interface first:((I)this).DoIt();. A bit ugly but it works.
If events could be explicitly implemented as ControlFlow (the OP) suggested, then how would you actually raise them? Consider:
public interface I
{
event EventHandler SomethingHappened;
}
public class C : I
{
public void OnSomethingHappened()
{
// Same problem as above
SomethingHappened(this, EventArgs.Empty);
}
event EventHandler I.SomethingHappened;
}
Here you cannot even raise the event by upcasting to the interface first, because events can only be raised from within the implementing class. It therefore seems to make perfect sense to require accessor syntax for explicitly implemented events.
When explicitly implementing an event that was declared in an interface, you must use manually provide the add and remove event accessors that are typically provided by the compiler. The accessor code can connect the interface event to another event in your class or to its own delegate type.
For example, this will trigger error CS0071:
public delegate void MyEvent(object sender);
interface ITest
{
event MyEvent Clicked;
}
class Test : Itest
{
event MyEvent ITest.Clicked; // CS0071
public static void Main() { }
}
The correct way would be:
public delegate void MyEvent(object sender);
interface ITest
{
event MyEvent Clicked;
}
class Test : Itest
{
private MyEvent clicked;
event MyEvent Itest.Clicked
{
add
{
clicked += value;
}
remove
{
clicked -= value;
}
}
public static void Main() { }
}
see Compiler Error CS0071
This would not actually be an original thought by myself.
However, I thought I might respond to this:
"Off the top of my head I don't see any theoretical or practical reason why we could not have field-like explicitly implemented events. Nor do I see any reason why we particularly need to. This may have to remain one of the mysteries of the unknown."
-Eric Lippert
In Chapter 23 of A Programmer's Introduction to C#, Second Edition, Eric Gunnerson wrote:
"[I]f another class also wanted to be called when the button was clicked, the += operator could be used, like this:
button.Click += new Button.ClickHandler(OtherMethodToCall);
Unfortunately, if the other class wasn't careful, it might do the following:
button.Click = new Button.ClickHandler(OtherMethodToCall);
This would be bad, as it would mean that our ButtonHandler would be unhooked and only the new method would be called."
...
"What is needed is some way of protecting the delegate field so that it is only accessed using += and -=."
He goes on over the next few pages to comment on including the add() and remove() methods to implement this behavior; being able to write to those methods directly and the consequence of storage allocation for unneeded delegate references.
I would add more, but I respect the author too much to do so without his permission. I recommend finding a copy of this book and would recommend anything by Eric Gunnerson in general (blog, etc...)
Anyway, I hope this is relevant to the topic and if so, hope it shines light on this "mystery of the unknown"? (I was reading this very chapter and searching Stack Overflow for insight into event handler logic considerations when creating custom collections from custom objects) - I only mention this because I claim no specific authority on this particular subject. I am merely a student in search of "enlightenment" myself :-)

Event vs Delegates [duplicate]

What are the differences between delegates and an events? Don't both hold references to functions that can be executed?
An Event declaration adds a layer of abstraction and protection on the delegate instance. This protection prevents clients of the delegate from resetting the delegate and its invocation list and only allows adding or removing targets from the invocation list.
To understand the differences you can look at this 2 examples
Example with Delegates (in this case, an Action - that is a kind of delegate that doesn't return a value)
public class Animal
{
public Action Run {get; set;}
public void RaiseEvent()
{
if (Run != null)
{
Run();
}
}
}
To use the delegate, you should do something like this:
Animal animal= new Animal();
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running") ;
animal.RaiseEvent();
This code works well but you could have some weak spots.
For example, if I write this:
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running");
animal.Run = () => Console.WriteLine("I'm sleeping") ;
with the last line of code, I have overridden the previous behaviors just with one missing + (I have used = instead of +=)
Another weak spot is that every class which uses your Animal class can invoke the delegate directly. For example, animal.Run() or animal.Run.Invoke() are valid outside the Animal class.
To avoid these weak spots you can use events in c#.
Your Animal class will change in this way:
public class ArgsSpecial : EventArgs
{
public ArgsSpecial (string val)
{
Operation=val;
}
public string Operation {get; set;}
}
public class Animal
{
// Empty delegate. In this way you are sure that value is always != null
// because no one outside of the class can change it.
public event EventHandler<ArgsSpecial> Run = delegate{}
public void RaiseEvent()
{
Run(this, new ArgsSpecial("Run faster"));
}
}
to call events
Animal animal= new Animal();
animal.Run += (sender, e) => Console.WriteLine("I'm running. My value is {0}", e.Operation);
animal.RaiseEvent();
Differences:
You aren't using a public property but a public field (using events, the compiler protects your fields from unwanted access)
Events can't be assigned directly. In this case, it won't give rise to the previous error that I have showed with overriding the behavior.
No one outside of your class can raise or invoke the event. For example, animal.Run() or animal.Run.Invoke() are invalid outside the Animal class and will produce compiler errors.
Events can be included in an interface declaration, whereas a field cannot
Notes:
EventHandler is declared as the following delegate:
public delegate void EventHandler (object sender, EventArgs e)
it takes a sender (of Object type) and event arguments. The sender is null if it comes from static methods.
This example, which uses EventHandler<ArgsSpecial>, can also be written using EventHandler instead.
Refer here for documentation about EventHandler
In addition to the syntactic and operational properties, there's also a semantical difference.
Delegates are, conceptually, function templates; that is, they express a contract a function must adhere to in order to be considered of the "type" of the delegate.
Events represent ... well, events. They are intended to alert someone when something happens and yes, they adhere to a delegate definition but they're not the same thing.
Even if they were exactly the same thing (syntactically and in the IL code) there will still remain the semantical difference. In general I prefer to have two different names for two different concepts, even if they are implemented in the same way (which doesn't mean I like to have the same code twice).
Here is another good link to refer to.
http://csharpindepth.com/Articles/Chapter2/Events.aspx
Briefly, the take away from the article - Events are encapsulation over delegates.
Quote from article:
Suppose events didn't exist as a concept in C#/.NET. How would another class subscribe to an event? Three options:
A public delegate variable
A delegate variable backed by a property
A delegate variable with AddXXXHandler and RemoveXXXHandler methods
Option 1 is clearly horrible, for all the normal reasons we abhor public variables.
Option 2 is slightly better, but allows subscribers to effectively override each other - it would be all too easy to write someInstance.MyEvent = eventHandler; which would replace any existing event handlers rather than adding a new one. In addition, you still need to write the properties.
Option 3 is basically what events give you, but with a guaranteed convention (generated by the compiler and backed by extra flags in the IL) and a "free" implementation if you're happy with the semantics that field-like events give you. Subscribing to and unsubscribing from events is encapsulated without allowing arbitrary access to the list of event handlers, and languages can make things simpler by providing syntax for both declaration and subscription.
What a great misunderstanding between events and delegates!!! A delegate specifies a TYPE (such as a class, or an interface does), whereas an event is just a kind of MEMBER (such as fields, properties, etc). And, just like any other kind of member an event also has a type. Yet, in the case of an event, the type of the event must be specified by a delegate. For instance, you CANNOT declare an event of a type defined by an interface.
Concluding, we can make the following Observation: the type of an event MUST be defined by a delegate. This is the main relation between an event and a delegate and is described in the section II.18 Defining events of ECMA-335 (CLI) Partitions I to VI:
In typical usage, the TypeSpec (if present) identifies a delegate whose signature matches the arguments passed to the event’s fire method.
However, this fact does NOT imply that an event uses a backing delegate field. In truth, an event may use a backing field of any different data structure type of your choice. If you implement an event explicitly in C#, you are free to choose the way you store the event handlers (note that event handlers are instances of the type of the event, which in turn is mandatorily a delegate type---from the previous Observation). But, you can store those event handlers (which are delegate instances) in a data structure such as a List or a Dictionary or any other else, or even in a backing delegate field. But don’t forget that it is NOT mandatory that you use a delegate field.
NOTE: If you have access to C# 5.0 Unleashed, read the "Limitations on Plain Use of Delegates" in Chapter 18 titled "Events" to understand better the differences between the two.
It always helps me to have a simple, concrete example. So here's one for the community. First I show how you can use delegates alone to do what Events do for us. Then I show how the same solution would work with an instance of EventHandler. And then I explain why we DON'T want to do what I explain in the first example. This post was inspired by an article by John Skeet.
Example 1: Using public delegate
Suppose I have a WinForms app with a single drop-down box. The drop-down is bound to an List<Person>. Where Person has properties of Id, Name, NickName, HairColor. On the main form is a custom user control that shows the properties of that person. When someone selects a person in the drop-down the labels in the user control update to show the properties of the person selected.
Here is how that works. We have three files that help us put this together:
Mediator.cs -- static class holds the delegates
Form1.cs -- main form
DetailView.cs -- user control shows all details
Here is the relevant code for each of the classes:
class Mediator
{
public delegate void PersonChangedDelegate(Person p); //delegate type definition
public static PersonChangedDelegate PersonChangedDel; //delegate instance. Detail view will "subscribe" to this.
public static void OnPersonChanged(Person p) //Form1 will call this when the drop-down changes.
{
if (PersonChangedDel != null)
{
PersonChangedDel(p);
}
}
}
Here is our user control:
public partial class DetailView : UserControl
{
public DetailView()
{
InitializeComponent();
Mediator.PersonChangedDel += DetailView_PersonChanged;
}
void DetailView_PersonChanged(Person p)
{
BindData(p);
}
public void BindData(Person p)
{
lblPersonHairColor.Text = p.HairColor;
lblPersonId.Text = p.IdPerson.ToString();
lblPersonName.Text = p.Name;
lblPersonNickName.Text = p.NickName;
}
}
Finally we have the following code in our Form1.cs. Here we are Calling OnPersonChanged, which calls any code subscribed to the delegate.
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
Mediator.OnPersonChanged((Person)comboBox1.SelectedItem); //Call the mediator's OnPersonChanged method. This will in turn call all the methods assigned (i.e. subscribed to) to the delegate -- in this case `DetailView_PersonChanged`.
}
Ok. So that's how you would get this working without using events and just using delegates. We just put a public delegate into a class -- you can make it static or a singleton, or whatever. Great.
BUT, BUT, BUT, we do not want to do what I just described above. Because public fields are bad for many, many reason. So what are our options? As John Skeet describes, here are our options:
A public delegate variable (this is what we just did above. don't do this. i just told you above why it's bad)
Put the delegate into a property with a get/set (problem here is that subscribers could override each other -- so we could subscribe a bunch of methods to the delegate and then we could accidentally say PersonChangedDel = null, wiping out all of the other subscriptions. The other problem that remains here is that since the users have access to the delegate, they can invoke the targets in the invocation list -- we don't want external users having access to when to raise our events.
A delegate variable with AddXXXHandler and RemoveXXXHandler methods
This third option is essentially what an event gives us. When we declare an EventHandler, it gives us access to a delegate -- not publicly, not as a property, but as this thing we call an event that has just add/remove accessors.
Let's see what the same program looks like, but now using an Event instead of the public delegate (I've also changed our Mediator to a singleton):
Example 2: With EventHandler instead of a public delegate
Mediator:
class Mediator
{
private static readonly Mediator _Instance = new Mediator();
private Mediator() { }
public static Mediator GetInstance()
{
return _Instance;
}
public event EventHandler<PersonChangedEventArgs> PersonChanged; //this is just a property we expose to add items to the delegate.
public void OnPersonChanged(object sender, Person p)
{
var personChangedDelegate = PersonChanged as EventHandler<PersonChangedEventArgs>;
if (personChangedDelegate != null)
{
personChangedDelegate(sender, new PersonChangedEventArgs() { Person = p });
}
}
}
Notice that if you F12 on the EventHandler, it will show you the definition is just a generic-ified delegate with the extra "sender" object:
public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
The User Control:
public partial class DetailView : UserControl
{
public DetailView()
{
InitializeComponent();
Mediator.GetInstance().PersonChanged += DetailView_PersonChanged;
}
void DetailView_PersonChanged(object sender, PersonChangedEventArgs e)
{
BindData(e.Person);
}
public void BindData(Person p)
{
lblPersonHairColor.Text = p.HairColor;
lblPersonId.Text = p.IdPerson.ToString();
lblPersonName.Text = p.Name;
lblPersonNickName.Text = p.NickName;
}
}
Finally, here's the Form1.cs code:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
Mediator.GetInstance().OnPersonChanged(this, (Person)comboBox1.SelectedItem);
}
Because the EventHandler wants and EventArgs as a parameter, I created this class with just a single property in it:
class PersonChangedEventArgs
{
public Person Person { get; set; }
}
Hopefully that shows you a bit about why we have events and how they are different -- but functionally the same -- as delegates.
You can also use events in interface declarations, not so for delegates.
Delegate is a type-safe function pointer. Event is an implementation of publisher-subscriber design pattern using delegate.
An event in .net is a designated combination of an Add method and a Remove method, both of which expect some particular type of delegate. Both C# and vb.net can auto-generate code for the add and remove methods which will define a delegate to hold the event subscriptions, and add/remove the passed in delegagte to/from that subscription delegate. VB.net will also auto-generate code (with the RaiseEvent statement) to invoke the subscription list if and only if it is non-empty; for some reason, C# doesn't generate the latter.
Note that while it is common to manage event subscriptions using a multicast delegate, that is not the only means of doing so. From a public perspective, a would-be event subscriber needs to know how to let an object know it wants to receive events, but it does not need to know what mechanism the publisher will use to raise the events. Note also that while whoever defined the event data structure in .net apparently thought there should be a public means of raising them, neither C# nor vb.net makes use of that feature.
To define about event in simple way:
Event is a REFERENCE to a delegate with two restrictions
Cannot be invoked directly
Cannot be assigned values directly (e.g eventObj = delegateMethod)
Above two are the weak points for delegates and it is addressed in event. Complete code sample to show the difference in fiddler is here https://dotnetfiddle.net/5iR3fB .
Toggle the comment between Event and Delegate and client code that invokes/assign values to delegate to understand the difference
Here is the inline code.
/*
This is working program in Visual Studio. It is not running in fiddler because of infinite loop in code.
This code demonstrates the difference between event and delegate
Event is an delegate reference with two restrictions for increased protection
1. Cannot be invoked directly
2. Cannot assign value to delegate reference directly
Toggle between Event vs Delegate in the code by commenting/un commenting the relevant lines
*/
public class RoomTemperatureController
{
private int _roomTemperature = 25;//Default/Starting room Temperature
private bool _isAirConditionTurnedOn = false;//Default AC is Off
private bool _isHeatTurnedOn = false;//Default Heat is Off
private bool _tempSimulator = false;
public delegate void OnRoomTemperatureChange(int roomTemperature); //OnRoomTemperatureChange is a type of Delegate (Check next line for proof)
// public OnRoomTemperatureChange WhenRoomTemperatureChange;// { get; set; }//Exposing the delegate to outside world, cannot directly expose the delegate (line above),
public event OnRoomTemperatureChange WhenRoomTemperatureChange;// { get; set; }//Exposing the delegate to outside world, cannot directly expose the delegate (line above),
public RoomTemperatureController()
{
WhenRoomTemperatureChange += InternalRoomTemperatuerHandler;
}
private void InternalRoomTemperatuerHandler(int roomTemp)
{
System.Console.WriteLine("Internal Room Temperature Handler - Mandatory to handle/ Should not be removed by external consumer of ths class: Note, if it is delegate this can be removed, if event cannot be removed");
}
//User cannot directly asign values to delegate (e.g. roomTempControllerObj.OnRoomTemperatureChange = delegateMethod (System will throw error)
public bool TurnRoomTeperatureSimulator
{
set
{
_tempSimulator = value;
if (value)
{
SimulateRoomTemperature(); //Turn on Simulator
}
}
get { return _tempSimulator; }
}
public void TurnAirCondition(bool val)
{
_isAirConditionTurnedOn = val;
_isHeatTurnedOn = !val;//Binary switch If Heat is ON - AC will turned off automatically (binary)
System.Console.WriteLine("Aircondition :" + _isAirConditionTurnedOn);
System.Console.WriteLine("Heat :" + _isHeatTurnedOn);
}
public void TurnHeat(bool val)
{
_isHeatTurnedOn = val;
_isAirConditionTurnedOn = !val;//Binary switch If Heat is ON - AC will turned off automatically (binary)
System.Console.WriteLine("Aircondition :" + _isAirConditionTurnedOn);
System.Console.WriteLine("Heat :" + _isHeatTurnedOn);
}
public async void SimulateRoomTemperature()
{
while (_tempSimulator)
{
if (_isAirConditionTurnedOn)
_roomTemperature--;//Decrease Room Temperature if AC is turned On
if (_isHeatTurnedOn)
_roomTemperature++;//Decrease Room Temperature if AC is turned On
System.Console.WriteLine("Temperature :" + _roomTemperature);
if (WhenRoomTemperatureChange != null)
WhenRoomTemperatureChange(_roomTemperature);
System.Threading.Thread.Sleep(500);//Every second Temperature changes based on AC/Heat Status
}
}
}
public class MySweetHome
{
RoomTemperatureController roomController = null;
public MySweetHome()
{
roomController = new RoomTemperatureController();
roomController.WhenRoomTemperatureChange += TurnHeatOrACBasedOnTemp;
//roomController.WhenRoomTemperatureChange = null; //Setting NULL to delegate reference is possible where as for Event it is not possible.
//roomController.WhenRoomTemperatureChange.DynamicInvoke();//Dynamic Invoke is possible for Delgate and not possible with Event
roomController.SimulateRoomTemperature();
System.Threading.Thread.Sleep(5000);
roomController.TurnAirCondition (true);
roomController.TurnRoomTeperatureSimulator = true;
}
public void TurnHeatOrACBasedOnTemp(int temp)
{
if (temp >= 30)
roomController.TurnAirCondition(true);
if (temp <= 15)
roomController.TurnHeat(true);
}
public static void Main(string []args)
{
MySweetHome home = new MySweetHome();
}
}
For people live in 2020, and want a clean answer...
Definitions:
delegate: defines a function pointer.
event: defines
(1) protected interfaces, and
(2) operations(+=, -=), and
(3) advantage: you don't need to use new keyword anymore.
Regarding the adjective protected:
// eventTest.SomeoneSay = null; // Compile Error.
// eventTest.SomeoneSay = new Say(SayHello); // Compile Error.
Also notice this section from Microsoft: https://learn.microsoft.com/en-us/dotnet/standard/events/#raising-multiple-events
Code Example:
with delegate:
public class DelegateTest
{
public delegate void Say(); // Define a pointer type "void <- ()" named "Say".
private Say say;
public DelegateTest() {
say = new Say(SayHello); // Setup the field, Say say, first.
say += new Say(SayGoodBye);
say.Invoke();
}
public void SayHello() { /* display "Hello World!" to your GUI. */ }
public void SayGoodBye() { /* display "Good bye!" to your GUI. */ }
}
with event:
public class EventTest
{
public delegate void Say();
public event Say SomeoneSay; // Use the type "Say" to define event, an
// auto-setup-everything-good field for you.
public EventTest() {
SomeoneSay += SayHello;
SomeoneSay += SayGoodBye;
SomeoneSay();
}
public void SayHello() { /* display "Hello World!" to your GUI. */ }
public void SayGoodBye() { /* display "Good bye!" to your GUI. */ }
}
Reference:
Event vs. Delegate - Explaining the important differences between the Event and Delegate patterns in C# and why they're useful.: https://dzone.com/articles/event-vs-delegate

Categories