C# delegate v.s. EventHandler - c#

I want to send an alert message to any subscribers when a trap occurred.
The code I created works fine using a delegate method myDelegate del.
My questions are:
I want to know whether it's better to use EventHandler instead of a delegate?
I'm not sure what the differences are between a delegate and an EventHandler in my case.
notify(trapinfo t), that's what I've done here to get trap information. But it seems not to be a good idea. I read some online tutorial lesson introducing passing delegate object; I'm wondering if it's appropriate in my case? And how should I do it? Any suggestions?
Thanks a lot :)
My code:
public class trapinfo
{
public string info;
public string ip;
public string cause;
}
public class trap
{
public delegate void myDelegate(trapinfo t);
public myDelegate del;
trapinfo info = new trapinfo();
public void run()
{
//While(true)
// If a trap occurred, notify the subscriber
for (; ; )
{
Thread.Sleep(500);
foreach (myDelegate d in del.GetInvocationList())
{
info.cause = "Shut Down";
info.ip = "192.168.0.1";
info.info = "Test";
d.Invoke(info);
}
}
}
}
public class machine
{
private int _occuredtime=0;
public trapinfo info = new trapinfo();
public void notify(trapinfo t)
{
++_occuredtime;
info.cause = t.cause;
info.info = t.info;
info.ip = t.ip;
getInfo();
}
public void subscribe(trap t)
{
t.del += new trap.myDelegate(notify);
}
public void getInfo()
{
Console.WriteLine("<Alert>: cauese/{0}, info/ {1}, ip/{2}, time/{3}",
info.cause, info.info, info.ip,_occuredtime);
}
}
class Program
{
static void Main(string[] args)
{
trap t = new trap();
machine machineA = new machine();
machineA.subscribe(t);
t.run();
}
}
Update 2013-08-12
How about the observer/observable design pattern, that looks great in my case (EventHandler).
In my case, a machine subscribes to a trap messenger. (Add a machine to an invocation list)
Once a trap occurred, I send a message to all machines which are subscribed. (Call HandleEvent to handle it)
Advantages:
don't care about GetInvocationList() anymore, just use (+=) and (-=) to decide whom to send the trap.
It's easier to understand the logic of my program.
I know there are several ways to do it, but I wish I could analyze its pros and cons.
And thanks for your comments and suggestions, that would be very helpful!
I read the MSDN EventArgs article which Matthew Watson suggested.
Here's my Event Version:
public class TrapInfoEventArgs : EventArgs
{
public int info { get; set; }
public string ip { get; set; }
public string cause { get; set; }
}
public class trap
{
public event EventHandler<TrapInfoEventArgs> TrapOccurred;
protected virtual void OnTrapOccurred(TrapInfoEventArgs e)
{
EventHandler<TrapInfoEventArgs> handler = TrapOccurred;
if (handler != null)
{
handler(this, e);
}
}
public void run()
{
//While(true)
// If a trap occurred, notify the subscriber
for (; ; )
{
Thread.Sleep(500);
TrapInfoEventArgs args = new TrapInfoEventArgs();
args.cause = "Shut Down";
OnTrapOccurred(args);
}
}
}
public class machine
{
public void c_TrapOccurred(object sender, TrapInfoEventArgs e)
{
Console.WriteLine("<Alert>: cauese/{0}, info/ {1}, ip/{2}, time/{3}",
e.cause, e.info, e.ip, DateTime.Now.ToString());
}
}
class Program
{
static void Main(string[] args)
{
trap t = new trap();
machine machineA = new machine();
t.TrapOccurred += machineA.c_TrapOccurred; //notify machine A
t.run();
}
}

The difference between event and delegate is that:
event declaration adds a layer of 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
See What are the differences between delegates and events?
2) As I see it, your subscriber should not change delegates freely. One subscriber can assign = to it instead of adding +=. This will assign a new delegate, therefore, the previous delegate with its invocation list will be lost and previous subscribers will not be called anymore. So you should use Event for sure. Or you can change your code to make your delegate private and write additional functions for manipulating it to define your own event behavior.
//preventing direct assignment
private myDelegate del ;
public void AddCallback(myDelegate m){
del += m;
}
public void RemoveCallback(myDelegate m){
del -= m;
}
//or
public static trap operator +(trap x,myDelegate m){
x.AddCallback(m);
return x;
}
public static trap operator -(trap x, myDelegate m)
{
x.RemoveCallback(m);
return x;
}
//usage
//t.AddCallback(new trap.myDelegate(notify));
t+=new trap.myDelegate(notify);

It is much better to use an event for your example.
An event is understood by the Visual Studio Form and WPF designers, so you can use the IDE to subscribe to events.
When raising events, there is no need for you to write your own foreach handling to iterate through them.
events are the way that most programmers will expect this functionality to be accessed.
If you use a delegate, the consuming code can mess around with it in ways that you will want to prevent (such as resetting its invocation list). events do not allow that to happen.
As for your second question: Using an event you would create a class derived from EventArgs to hold the data, and pass that to the event when you raise it. The consumer will then have access to it.
See here for details: http://msdn.microsoft.com/en-us/library/system.eventargs.aspx

Related

Adapting C# event containing ref parameter

I'm in a situation where I have to use 3rd party library that contains a lot of events and is imho not very well written. It fires up events that I have to handle in my code, but I'm trying to abstract it away (to be able to unit test rest of my code dependent on that library) so I need an adapter. The problem is that some of the events are of delegate type that take ref parameters. Here's an example of how the 3rd party library looks like:
delegate void AdapteeEventHandler1(SpecificAdaptee sender, int a, int b);
delegate void AdapteeEventHandler2(SpecificAdaptee sender, ref int a); // problematic delegate
class SpecificAdaptee
{
public event AdapteeEventHandler1 Event1;
public event AdapteeEventHandler2 Event2; // problematic event
/// <summary>Exercise Event1</summary>
public void FireEvent1()
{
Event1?.Invoke(this, 1, 2);
}
/// <summary>Exercise Event2</summary>
public void FireEvent2()
{
int a = 42;
Event2?.Invoke(this, ref a);
}
}
To show how I am abstracting regular event taking list of parameters, it contains Event1 of type AdapteeEventHandler1. The problematic type is AdapteeEventHandler2, but let me show first how I am going about adapting the whole thing:
#region AdaptedEventArgs
class AdaptedEventArgs1 : EventArgs
{
public int A { get; set; }
public int B { get; set; }
}
class AdaptedEventArgs2 : EventArgs
{
public int A { get; set; }
}
#endregion
/// <summary>These represent an abstraction layer between SpecificAdaptee and our own code</summary>
class Adaptor
{
private readonly SpecificAdaptee _specificAdaptee;
/// <summary>Maintains relationship between the event triggered by SpecificAdaptee and the adapted event.</summary>
private readonly IAdaptedEventHandlerManager _adaptedEventHandlerManager;
public Adaptor(SpecificAdaptee specificAdaptee, IAdaptedEventHandlerManager adaptedEventHandlerManager)
{
_specificAdaptee = specificAdaptee;
_adaptedEventHandlerManager = adaptedEventHandlerManager;
}
#region Events
/// <summary>Adapts SpecificAdaptee.Event1</summary>
public event EventHandler<AdaptedEventArgs1> AdaptedEvent1
{
add
{
_specificAdaptee.Event1 += _adaptedEventHandlerManager.RegisterEventHandler<AdapteeEventHandler1>(value,
(sender, a, b) => value.Invoke(this, new AdaptedEventArgs1 { A = a, B = b }));
}
remove
{
_specificAdaptee.Event1 -= _adaptedEventHandlerManager.UnregisterEventHandler<AdapteeEventHandler1>(value);
}
}
/// <summary>Adapts SpecificAdaptee.Event2</summary>
public event EventHandler<AdaptedEventArgs2> AdaptedEvent2
{
add
{
/* !!! ERROR HERE !!! */
_specificAdaptee.Event2 += _adaptedEventHandlerManager.RegisterEventHandler<AdapteeEventHandler2>(value,
(sender, a) => value.Invoke(this, new AdaptedEventArgs2 { A = a }));
}
remove
{
_specificAdaptee.Event2 -= _adaptedEventHandlerManager.UnregisterEventHandler<AdapteeEventHandler2>(value);
}
}
#endregion
}
So what is happening here is that when I register an event handler to Adaptor.AdaptedEvent1 I am wrapping EventHandler<AdaptedEventArgs1> in AdapteeEventHandler1 and register it to SpecificAdaptee.Event1, also converting the AdaptedEventArgs1 to list of parameters required by AdapteeEventHandler1. This way user can register to events of Adaptor that will be fired when SpecificAdaptee fires its own events. Next I will post a program that exercises this but note that the problem is in AdaptedEvent2, where I would like to do things in an analogous manner, but I don't know how to deal with the ref parameter (there is a syntax error in add accessor of AdaptedEvent2.
Here is a console application exercising the project:
class Program
{
public static void Main(string[] args)
{
var specific = new SpecificAdaptee();
var adapter = new Adaptor(specific, new AdaptedEventHandlerManager());
adapter.AdaptedEvent1 += OnAdaptedEvent1;
adapter.AdaptedEvent2 += OnAdaptedEvent2;
specific.FireEvent1();
specific.FireEvent2();
Console.ReadLine();
}
private static void OnAdaptedEvent1(object sender, AdaptedEventArgs1 args)
{
Console.WriteLine($"{nameof(OnAdaptedEvent1)}({sender}, {args.A}, {args.B})");
}
private static void OnAdaptedEvent2(object sender, AdaptedEventArgs2 args)
{
Console.WriteLine($"{nameof(OnAdaptedEvent2)}({sender}, {args.A})");
}
}
So that's how it's supposed to work. I register to events of my Adaptor that I have in my code, and events get fired when the 3rd party library (SpecificAdaptee) fires its own events (here in this example, triggered by calling specific.FireEvent1() and 2).
For completeness, so you can try it yourself I include code for AdaptedEventHandlerManager that maps adapted event handlers to SpecificAdaptee's handlers, so I can register and unregister multiple event handlers like I normally would do:
interface IAdaptedEventHandlerManager
{
TSpecificEventHandler RegisterEventHandler<TSpecificEventHandler>(object adaptedEventHandler,
TSpecificEventHandler specificEventHandler);
TSpecificEventHandler UnregisterEventHandler<TSpecificEventHandler>(object adaptedEventHandler)
where TSpecificEventHandler : class;
}
class AdaptedEventHandlerManager : IAdaptedEventHandlerManager
{
/// <summary>
/// Remembers relation between the specific handler and general handler. Important when unsubscribing from
/// events. Key is the general event handler we are registering to events of this class. Value are specific
/// event handlers.
/// </summary>
private readonly Dictionary<object, List<object>> _eventHandlers =
new Dictionary<object, List<object>>();
public TSpecificEventHandler RegisterEventHandler<TSpecificEventHandler>(object adaptedEventHandler,
TSpecificEventHandler specificEventHandler)
{
List<object> eventHandlerList;
if (!_eventHandlers.TryGetValue(adaptedEventHandler, out eventHandlerList))
{
eventHandlerList = new List<object> { specificEventHandler };
_eventHandlers.Add(adaptedEventHandler, eventHandlerList);
}
else
{
eventHandlerList.Add(specificEventHandler);
}
return specificEventHandler;
}
public TSpecificEventHandler UnregisterEventHandler<TSpecificEventHandler>(object adaptedEventHandler)
where TSpecificEventHandler : class
{
List<object> eventHandlerList;
if (!_eventHandlers.TryGetValue(adaptedEventHandler, out eventHandlerList))
{
return null;
}
var eventHandler = eventHandlerList.FirstOrDefault();
if (eventHandler != null)
{
eventHandlerList.Remove(eventHandler);
}
if (!eventHandlerList.Any())
{
_eventHandlers.Remove(adaptedEventHandler);
}
return eventHandler as TSpecificEventHandler;
}
}
This basically remembers in a dictionary the adapted event handler, and the list of SpecificAdaptee's handlers.
So my question: is there a way to adapt events taking ref parameters without retracting to custom delegate type that takes a ref parameter, so I can use standard EventHandler<> class with custom EventArgs descendant?
I realise it's quite a handful of code so please let me know if something is not clear. Thanks in advance.
ref parameter in the event is meant to set from the subscribers. Though it's a bad idea, the api which you're using works based on that.
You can take all the pain in the adapter class and make it work such that consumers are not polluted by the ref parameter. They can continue to use EventArgs style events.
public event EventHandler<AdaptedEventArgs2> AdaptedEvent2
{
add
{
_specificAdaptee.Event2 += _adaptedEventHandlerManager.RegisterEventHandler<AdapteeEventHandler2>(value,
(SpecificAdaptee sender, ref int a) =>
{
var args = new AdaptedEventArgs2 { A = a };
value.Invoke(this, args);
a = args.A;
});
}
remove
{
_specificAdaptee.Event2 -= _adaptedEventHandlerManager.UnregisterEventHandler<AdapteeEventHandler2>(value);
}
}
After the event is executed, we set the value of A to the ref parameter a. This simulates the behavior of ref parameter and also abstracts it under the adapter class. If A is changed in the event handler, it will be reflected in the SpecificAdaptee class too.
To show how this works like a ref parameter:
class SpecificAdaptee
{
...
public void FireEvent2()
{
int a = 42;
if (Event2 != null)
Event2(this, ref a);
Console.WriteLine("A value after the event is {0}", a);
}
}
private static void OnAdaptedEvent2(object sender, AdaptedEventArgs2 args)
{
Console.WriteLine($"{nameof(OnAdaptedEvent2)}({sender}, {args.A})");
args.A = 15;
}
This prints:
A value after the event is 15
PS: For brevity I've added only the parts of your program which needs a change.

Design pattern: child class calling base class

I have "Handlers" able to trigger "Brokers" (an object that does something - not important here).
Handlers are listening to different kind of events:
TimeEvent: Every 10 seconds, 10 minutes (...)
FileSystemEvent: Once a file copied/moved/deleted
DbEvent: When a record is added to a DB table
MailEvent: When I received an email in my Office 365 mailbox
Each handler must have:
Start and stop methods (start/stop catching events)
An instance of the associated broker
A way to "trigger" the broker (Process method + specific set of arguments).
Each handler should
Trigger the associated broker when a specific event is raised
I want to trigger brokers from the base Handler class so I centralize my logic (fire events, catch exception, manage threads etc.). However, the base handler doesn't know how to call the broker (when to call this function, what parameters to send to the Process method) >> Only specialized children handlers know how to do that.
The only way I found is to implement in the base handler an Execute method accepting an Action parameter... I don't like this approach as it's not really straight forward (child needs to call base class otherwise nothing happens). I was hoping to find a better design to handle this. In addition I can tell you my developers will tell me they don't understand how to use the system.
abstract class Handler : IHandler
{
public IBroker Broker { get; protected set; }
public event ProcessedEventHandler Processed;
protected void OnProcessed(ProcessExecutionResult result) => Processed?.Invoke(this, result);
public static IHandler Create(IBroker broker)
{
if (broker is ITimerTriggeredBroker)
return new TimeHandler((ITimerTriggeredBroker)broker);
return null;
}
protected Handler(IBroker broker)
{
if (broker == null) throw new ArgumentNullException(nameof(broker));
Broker = broker;
}
public abstract void Start();
public abstract void Stop();
protected void Execute(Action action)
{
var res = new ProcessExecutionResult();
try
{
action?.Invoke();
res.IsSuccess = true;
}
catch (Exception ex)
{
res.Exception = ex;
res.IsSuccess = false;
}
finally
{
OnProcessed(res);
}
}
}
TimeHandler (handling Time related events)
class TimeHandler : Handler
{
private readonly Timer _timer;
private readonly DateTime _start;
private readonly TimeSpan _frequency;
public TimeHandler(ITimerTriggeredBroker broker)
: base(broker)
{
_start = broker.Trigger.StartTime;
_frequency = broker.Trigger.Frequency;
_timer = new Timer(_ => Execute(broker.Process));
}
(...)
}
FileHandler (handling FileSystem related events)
class FileHandler : Handler
{
private readonly FileSystemWatcher _watcher = new FileSystemWatcher();
public FileHandler(IFileTriggeredBroker broker)
: base(broker)
{
if (!Directory.Exists(broker.Trigger.DirectoryPath))
throw new DirectoryNotFoundException("Unable to locate the supplied directory");
_watcher.Filter = broker.Trigger.Filter;
_watcher.Path = broker.Trigger.DirectoryPath;
_watcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.DirectoryName |
NotifyFilters.FileName;
_watcher.Created += (s, a) =>
{
if (IsCopied(a.FullPath)) Execute(() => broker.Process(a.FullPath));
};
}
There are several aspects to what you are trying to achieve:
The architecture should be easy to understand and follow by your programmers. It should guide them while they program and protect them from making errors.
It should be robust. For example, you should guarantee that every file created in the watched folder is processed.
In my answer I will ignore the robustness aspect. Please look at this seriously. FileSystemWatcher is not guaranteed to deliver all files created. Also, it is advisable to you separate the processing of FileSystemWatcher events in a separate thread or use .NET tasks for this.
Furthermore, I think you should consider using a queue, like Microsoft MQ, Azure Queue, RabbitMQ. You can do this directly or use a system like MassTransit.
Below I propose an architecture that will make it easier for your programmers to build upon.
General description
Divide the application in folders or different assemblies to make a clear separation between framework and specific handlers/brokers.
For each type of processing we create a specific message class and let the handler and broker implement a generic interface specific for the message type.
We will make use of the C# advanced type system to make sure that it is difficult to make mistakes and that the compiler will help the programmers to use the right things. For this we use generic interfaces and classes based on the message type class.
Main program
Here we will setup a manager that will register all handlers and brokers with their respective messages. This is a stand alone example, I suggest you use a system for dependency injection like for example AutoFac to further optimize this.
static void Main(string[] args)
{
var manager = new Manager();
manager.Register<FileHandlerMessage>(new FileHandler(), new FileBroker());
manager.Register<TimeHandlerMessage>(new TimeHandler(), new TimeBroker());
manager.Start();
Console.ReadLine();
manager.Stop();
}
Manager
The role of the Manager class is to organize for proper usage of handlers and brokers.
class Manager
{
private List<IGenericHandler> handlers = new List<IGenericHandler>();
public void Register<M>(IHandler<M> handler, IBroker<M> broker) where M : Message
{
handlers.Add(handler);
}
public void Start()
{
foreach ( var handler in handlers )
{
handler.Start();
}
}
public void Stop()
{
foreach (var handler in handlers)
{
handler.Stop();
}
}
}
Messages
For each type of broker, we will define a specific message class, derived from a common base class:
abstract class Message
{
}
class FileHandlerMessage : Message
{
public string FileName { get; set; }
}
Handlers
interface IGenericHandler
{
void Start();
void Stop();
}
interface IHandler<M> : IGenericHandler where M : Message
{
void SetBroker(IBroker<M> broker);
}
class FileHandler : IHandler<FileHandlerMessage>
{
private IBroker<FileHandlerMessage> broker;
public FileHandler()
{
}
public void SetBroker(IBroker<FileHandlerMessage> fileBroker)
{
this.broker = fileBroker;
}
public void Start()
{
// do something
var message = new FileHandlerMessage();
broker.Process(message);
}
public void Stop()
{
// do something
}
}
class TimeHandler : IHandler<TimeHandlerMessage>
{
private IBroker<TimeHandlerMessage> broker;
public void SetBroker(IBroker<TimeHandlerMessage> broker)
{
this.broker = broker;
}
public void Start()
{
// do something
var message = new TimeHandlerMessage();
broker.Process(message);
}
public void Stop()
{
// do something
throw new NotImplementedException();
}
}
Brokers
class FileBroker : IBroker<FileHandlerMessage>
{
public void Process(FileHandlerMessage message)
{
throw new NotImplementedException();
}
}
class TimeBroker : IBroker<TimeHandlerMessage>
{
public void Process(TimeHandlerMessage message)
{
throw new NotImplementedException();
}
}

raising events using event Action<T>

I'm used to using delegate EventHandler for event callbacks but now I'm attempting to use event Action for invoking events. I couldn't find much info on how this can be used properly anywhere so I'm hoping someone can point me in the right direction.
I have an Action event handler that handles string objects. In my subscriber class I have public event Action<string> UploadProgress;. The event handler is invoked like this:
UploadProgress.Invoke(string.Format("sending file data {0:0.000}%", (bytesSoFar * 100.0f) / totalToUpload));
The listener class is subscribed to this event as below:
uploadFile.UploadProgress += uploadFile_UploadProgress;
void uploadFile_UploadProgress(string obj)
{
var prog = obj;
}
When the event is invoked, I get System.NullReferenceException: Object reference not set to an instance of an object. I'm not sure what I need to change in the subscriber class to avoid this error. Can someone tell me the proper way to use event Action or provide me the link to where I can read up on it? I know how to use the normal Action but confused about declaring it as an event. Any help is appreciated.
This way is much better, send bytesToUpload and totalToUpload through event, instead of the whole Action (right sample):
internal class Program
{
private static void Main(string[] args)
{
SomeClass someClass = new SomeClass();
someClass.UploadProgress += SomeClass_UploadProgress;
someClass.DoSomeUpload();
}
private static void SomeClass_UploadProgress(object sender, UploadEventArgs e)
{
string s = string.Format("sending file data {0:0.000}%", (e.BytesSoFar * 100.0f) / e.TotalToUpload);
Console.WriteLine(s);
}
}
public class UploadEventArgs : EventArgs
{
public float BytesSoFar { get; set; }
public float TotalToUpload { get; set; }
}
public class SomeClass
{
public event EventHandler<UploadEventArgs> UploadProgress;
public void DoSomeUpload()
{
if (UploadProgress != null)
{
UploadEventArgs e = new UploadEventArgs();
e.BytesSoFar = 123f;
e.TotalToUpload = 100000f;
UploadProgress.Invoke(this, e);
}
}
}

Understanding Events in C#

I'm very new to programming, but I'm pretty sure I've almost got this Events thing down. I just need a few pointers, I guess. I'm trying to create a simple example of an Event, one that simply says "Hello!" every second or so. First I have my "Publisher" class:
public class Publisher
{
public delegate void MyEventHandler();
public event MyEventHandler MyEvent;
public void MyMethod()
{
while (true) { Thread.Sleep(1000); if (MyEvent != null) { MyEvent(); } }
}
}
Next, I have my "Subscriber" class:
public class Subscriber
{
public void Subscribe(Publisher TheObject)
{
TheObject.MyEvent += new Publisher.MyEventHandler(SayHello);
}
public void SayHello() { Console.WriteLine("Hello!"); }
}
Finally, in my Program:
public class Program {
static void Main(string[] args) {
var ThePublisher = new Publisher();
var TheSubscriber = new Subscriber();
TheSubscriber.Subscribe(ThePublisher);
ThePublisher.MyEvent();
}
}
The compiler says that I have an error though. It put a red line underneath "MyEvent" in "ThePublisher.MyEvent();" in Program. The error says "The event 'NameOfProject.Publisher.MyEvent' can only appear on the left hand side of += or -= (except when used from within the type 'NameOfProject.Publisher')" However, I know that I put in "+=" and nothing else. It is stated in my Subscriber class. What am I missing? What am I doing wrong?
In the last line, you're calling ThePublisher.MyEvent() instead of ThePublisher.MyMethod(), as you probably intended to do.
You may not trigger an event directly from outside the class which defines the event.

Purpose of "event" keyword

I am using c# and events alot lately but I'm just starting to create my own events and use them. I'm a little confused on why to use the event keyword, I got the same result by only using delegates.
public partial class Form1 : Form
{
ServerConnection connection = new ServerConnection();
public Form1()
{
InitializeComponent();
connection.ref = new del(MethOne);
connection.ref += new del(MethTwo);
}
public void MethOne(object message)
{
MessageBox.Show((string)message);
}
public void MethTwo(object message)
{
MessageBox.Show((string)message);
}
}
public delegate void del(string message);
public class ServerConnection
{
private TcpListener tcpListener;
public del ref;
private List<NetworkStream> clientList = new List<NetworkStream>();
public ServerConnection()
{
this.tcpListener = new TcpListener(IPAddress.Any, 3000);
ThreadStart startListening = new ThreadStart(ListenForClients);
Thread startThread = new Thread(startListening);
startThread.Start();
}
public void ListenForClients()
{
tcpListener.Start();
ParameterizedThreadStart handleClient = new ParameterizedThreadStart(HandleClient);
while (true)
{
TcpClient newClient = tcpListener.AcceptTcpClient();
Thread handleClientThread = new Thread(handleClient);
handleClientThread.Start(newClient);
}
}
public void HandleClient(object newClient)
{
NetworkStream clientStream = ((TcpClient)newClient).GetStream();
clientList.Add(clientStream);
BinaryFormatter formatter = new BinaryFormatter();
string message;
while (true)
{
message = (string)formatter.Deserialize(clientStream);
ref((string)message);
}
}
The event keyword lets you specify add and remove operations inline with the declaration.
private Action _myEvent;
public event Action MyEvent
{
add
{
Console.WriteLine("Listener added!");
_myEvent += value;
}
remove
{
Console.WriteLine("Listener removed!");
_myEvent -= value;
}
}
Have a look at
C# events vs. delegates
the event keyword is a modifier for a delegate declaration that allows
it to be included in an interface, constraints it invocation from
within the class that declares it, provides it with a pair of
customizable accessors (add and remove) and forces the signature of
the delegate (when used within the .NET framework).
The purpose is to identify what is an event, and what is just a callback.
Both seems to be the same thing, but the meaning is different.
Also Visual Studio places different icons to indicate events.
If I remember well, it the early days of C#, delegates didn't support this:
this.mydelegatefield += somethingHere;
Only events... but may be it is only my imagination.
EDIT
Just not to be missleading... there is the difference of add/remove methods. I place this after the other answers (since I forgot about this). So, credit is not mine.
Event is just a sugarcoat. 3 things happen when you define an event.
Simple EG:
public event EventHandler alarm;
Sample compiler output
private EventHandler alarm
public void add_alarm(EventHandler value)
{
}
public void remove_alarm(EventHandler value)
{
}
Notice private in contrast to your public del me;
Public accessors may cause problems. Also, using get and set is a better pattern
events can be compared to properties of your class.
Properties are interfaces to your MemberField/Object states.
Similarly event is an interface to the underlying delegate.
you can still achieve the endresult without event.But you lose encapsulation without events.
A non protected delegate can be prone to abuse.

Categories