Do I use a delegate or an event - c#

I have a Connection class which reads packets (commands) from a text stream and then distributes the commands to a set of handlers which process the commands as they see fit.
Eg.. Connection class reads in a command "HELLO" and then passes the command off to the handlers, where one or more handler may do something useful with the HELLO command.
Right now I use a delegate called HandleCommand which all command handlers must adhere to in order to receive the commands.
The question is, would it be more logical to use an event (eg.. CommandReceived) which the handlers could individually subscribe to? I'm having a hard time weighing up the pros and cons. it seems more wasteful to make it an event, because then an EventArgs class has to be generated for each command received.
In contrast, there is also a DisconnectCallback delegate which I strongly believe would be better as an event and will probably change.
Thank you

It seems your distributor now has to keep a list of handlers (class or delegates). That means you are duplicating the functionality of event.
The situation seems to call for events. It would decouple the components.
Concerning the 'wastefulness' of events and eventargs, see this question and stop worrying.

First - until you have evidence that it's a performance bottleneck, don't sacrifice clarity. The GC is fast and it's unlikely cleaning up a short-lived eventargs class will be the dominating performance factor here.
Anyway, If the consumers are only going to read and not modify the data, I'd make it an event. Otherwise you'd probably want to make an interface for a 'filter' that can read and modify, and pass the new value to the next one.

Events would be the most obvious approach as there are more than one command handlers.
I'm curious as to how command handlers "adhere" to a connection using delegates. You have to either simulate the event behavior by using a list of listeners or the command must actively call the handlers, what indeed compromises decoupling.

You are not required to use EventHandler or EventHandler<T> when creating an event, even though that is against Microsoft's recomendation. You can use your current delegate as the datatype for the event like so:
public event MyDelegateType EventName;
Edit:
If you are concerned about performance you can use an EventHandlerList class like so:
private EventHandlerList _events = new EventHandlerList();
private static object MyDelegateKey = new object()
public event MyDelegate EventName {
add {
_events.AddHandler(MyDelegateKey, value);
}
remove {
_events.RemoveHandler(MyDelegateKey, value);
}
}

Related

Is it always safe to unsubscribe from an event inside the handler?

Lets say that I have this (incomplete) class, in which I raise an event without first assigning it to a variable to make it thread-safe:
public class Test
{
public event EventHandler SomeEvent;
void OnSomeEvent(EventArgs e)
{
if (SomeEvent != null)
SomeEvent(this, e);
}
}
Would it be safe to unsubscribe an event handler from itself, or could there be any problem similar to what would happen when removing items from a collection while enumerating it?
void SomeEventHandler(object sender, EventArgs e)
{
testInstance.SomeEvent -= SomeEventHandler;
}
To clarify the other answer a bit:
Events are based on delegates (in almost all cases). Delegates are immutable. This applies to multicast delegates, too.
When invoking an event the delegate is loaded and then invoked. If the field that the delegate is stored in is modified then this does not affect the already loaded delegate.
It's therefore safe to modify the event from the handler. Those changes will not affect the currently running invocation. This is guaranteed.
All of this only applies to events backed by a delegate. C# and the CLR support custom events that could do anything at all.
It would be safe, however, just know it is not a guarantee that the code in SomeEventHandler will be executed only once. A race condition might occur if you have multithreaded code.
Edit:
Unsubscribing from an event will, behind the scenes, combine delegates to produce a list of delegates. (Lots of details can be found on that article by Jon Skeet the man himself)
Note that the event uses locks to guarantee thread safety on the Delegate combination. Once you have combined a delegate to your event, you will have a resulting list of delegates. When raising an event, however, what is not guaranteed is that the latest version of the combined delegates will be used. (see Thread-safe events) but this is unrelated to the fact the event was un-hooked from the inside of the event.
I hope my edit provides enough clarification :)

Not understanding the point with delegates/events and publisher/subscribers

I'm reading and reading, but I still can't get the point and how to use delegates/events and publisher/subscribers? I know that a delegate is a class that contains references to one or more methods and that it's used to send methods to another methods.
The thing I don't get is how I should determine the role of publischer/suubscriber. Let's take an example. A taxicentral and it's cabs. Is the taxicentral the publischer and the cabs the subscribers, whating to get driving orders from the taxicentral? But the cabs could also be publisher and report back there position and the address they are heading for to the taxicentral that, then is a subscriber of the cabs!?
I need inspiration and I'm looking for som beginners code to get a view of how this is working. Is there someone who have some minutes left to reply to this answer with some simple code? Thanks!
Another way to think of events, publishers/subscribers, etc...is to think of the cloud and the way it tends to function. In a cloud based system, any entity can register to listen for any type of event, OR can publish any event that it wants. Anyone listening, will get that data.
In your example: Taxi central could publish/push events like Shift Change, Traffic Accident as (Location), Taxi Requested at (Location), or other similar things that the entire group of cabs would be listening for. The individual cabs would be publishing things like Pickup At (Location), Drop Off at (Location), Accident at (Location); that Central would be logging for its own purposes. Other cabs could if they wanted to ALSO be listening for these same events, so that they would know where and how close other cabs are to their own location, or if there is an accident that another cab reported, or similar.
Cloud events however are a specific implementation of the event system. Its much more common to specifically subscribe to events. A cab object, when created, would immediately subscribe itself to the Central events, and the central system when dispatching the cab would make certain that it subscribed itself to that cab's events.
In this way, both objects serve the role of both publisher and subscriber. Its only really specific to a single event. In my example PickupAt(Location) would be published by a Cab, and Subscribed to by Central. Thus, for that event, Cab is the publisher, and Central is the Subscriber. In general, Who serves what role depends entirely on the system design and what events are being created. Its not something that can really be generalized, because the entire setup could be changed, or even reversed, if you setup the events differently. That I think is the most important part.
Delegates as a whole
In its simplest term, a Delegate is a Reference. It can reference a class, more commonly it can reference a method in a class, or the call to a method in a class. It can even contain an entire method call inside itself. Its really a very versatile object, in that it can do many things. In the context of events, the delegate actually references the call to the function that implements the event.
Simple Event Code
public class c1
{
public event Eventhandler DoStuff;
public c1()
{
}
public void OnDoStuff()
{//this actually makes the event happen
if (DoStuff != null)
DoStuff(this, null);
}
}
public static void Main()
{
c1 x = new c1();
x.DoStuff += new EventHandler(ThingFunction);
x.OnDoStuff();//this is how you would fire the event deliberately
}
public void ThingFunction(object sender, EventArgs x)
{
Console.WriteLine("Something Happened");
}
c1 contains the event DoStuff, Main subscribes to this event. When the code calls x.OnDoStuff() from ANYWHERE, which is very handy if say you pass x, or a reference to it, into other classes where actual code is processed, then the handler way back in main, no matter how many layers deep the x.OnDoStuff() call originates from, will execute.
Rather more specifically, once X is created, it can be passed somewhere else. As long as some function is assigned to x.DoStuff, whenever and wherever you call the method x.OnDoStuff() from, the function that is assigned to x.DoStuff will execute. That is how event subscriptions work. x.OnDoStuff() is the code call that publishes the event x.DoStuff, and any class...in fact any number of classes, you can have multiple subscribers after all, will be able to catch the published event.
You have to think in "Event Driven" terms. In your example there could be publisher roles for both the taxicentral and the cabs as well as subscriber roles for the taxicentral and cab.
For example, if the taxicentral has an update to push to all the cabs it can have an event that it raises and the cabs listen to. Cabs then could have an event they raise when they pick up and drop off someone, and the taxicentral would listen to all those events.
Does this help?
Delegates are not used to send methods to other methods. They are used to call methods, which may be unknown at compile time.
Let's look at a simpe example. Consider, you write a calculator, where the user can choose the arguments and the operation. The operation can be a delegate to a method that executes the calculation. Therefore, you don't have to worry about how to store the operations. Furthermore, the calculator does not need to know every operation, because the user will provide it.
A common example of delegates are callback functions. If you start a long term procedure in a second thread, you may want to be notified, if the thread has finished. You could do this by providing a delegate to the thread that is invoked, when the procedure has finished.
Events are kind of a special type of delegates. They are used, when an object wants to notify others of a status change or similar actions. The special thing about that is that the object itself does not need to know, which objects are interested in the changes. Instead, those objects subscribe to the event. The object that provides the event only has to invoke the event's delegate and all subscriber delegates are invoked.
As Justin C already explained, both the taxi central and the cab can act as subscribers and publishers. It depends on who is interested in what. And if everyone is allowed to subscribe to the events. If only the taxi central is allowed to get the information, a callback method would be more suitable.

How can I retrieve all methods of an event?

I have an event Load
public delegate void OnLoad(int i);
public event OnLoad Load;
I subscribe to it with a method:
public void Go()
{
Load += (x) => { };
}
Is it possible to retrieve this method using reflection? How?
In this particular case you could, with reflection. However, in general, you can't. Events encapsulate the idea of subscribers subscribing and unsubscribing - and that's all. A subscriber isn't meant to find out what other subscribers there are.
A field-like event as you've just shown is simply backed by a field of the relevant delegate type, with autogenerated add/remove handlers which just use the field. However, there's nothing to say they have to be implemented like that. For example, an event can store its subscribers in an EventHandlerList, which is efficient if you have several events in a class and only a few of them are likely to be subscribed to.
Now I suppose you could try to find the body of the "add" handler, decompile it and work out how the event handlers are being stored, and fetch them that way... but please don't. You're creating a lot of work, just to break encapsulation. Just redesign your code so that you don't need to do this.
EDIT: I've been assuming that you're talking about getting the subscribers from outside the class declaring the event. If you're inside the class declaring the event, then it's easy, because you know how the event is being stored.
At that point, the problem goes from "fetching the subscribers of an event" to "fetching the individual delegates making up a multicast delegate" - and that's easy. As others have said, you can call Delegate.GetInvocationList to get an array of delegates... and then use the Delegate.Method property to get the method that that particular delegate targets.
Now, let's look again at your subscription code:
public void Go()
{
Load += (x) => { };
}
The method that's used to create the delegate here isn't Go... it's a method created by the C# compiler. It will have an "unspeakable name" (usually with angle brackets) so will look something like this:
[CompilerGenerated]
private static void <Go>b__0(int x)
{
}
Now, is that actually what you want to retrieve? Or were you really looking to find out which method performed the subscription, rather than which method was used as the subscribed handler?
If you call Load.GetInvocationList() you will be handed back an array of Delegate types. From the these types, you can access the MethodInfo.
You could use the GetInvocationList method which will give you all the subscribers.

Explicit Event add/remove, misunderstood?

I've been looking into memory management a lot recently and have been looking at how events are managed, now, I'm seeing the explicit add/remove syntax for the event subscription.
I think it's pretty simple, add/remove just allows me to perform other logic when I subscribe and unsubscribe? Am I getting it, or is there more to it?
Also, while I'm here, any advice / best practices for cleaning up my event handles.
The add/remove properties are basically of the same logic of using set/get properties with other members.
It allows you to create some extra logic while registering for an event, and encapsulates the event itself.
A good example for WHY you'd want to do it, is to stop extra computation when it's not needed (no one is listening to the event).
For example, lets say the events are triggered by a timer, and we don't want the timer to work if no-one is registered to the event:
private System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
private EventHandler _explicitEvent;
public event EventHandler ExplicitEvent
{
add
{
if (_explicitEvent == null) timer.Start();
_explicitEvent += value;
}
remove
{
_explicitEvent -= value;
if (_explicitEvent == null) timer.Stop();
}
}
You'd probably want to lock the add/remove with an object (an afterthought)...
Yes, the add/remove syntax allows you to implement your own subscription logic. When you leave them out (the standard notation for an event) the compiler generates standard implementations. That is like the auto-properties.
In the following sample, there is no real difference between Event1 and Event2.
public class Foo
{
private EventHandler handler;
public event EventHandler Event1
{
add { handler += value; }
remove { handler -= value; }
}
public event EventHandler Event2;
}
But this is a separate topic from 'cleaning up' handlers. It is the subscribing class that should do the unsubscribe. The publishing class can not help with this very much.
Imagine a class that would 'clean' up the subscription list of its events. It can only sensibly do this when it is Disposed itself, and then it is unlikely to be productive as a Disposed class usually becomes collectable shortly after it is Disposed.
Add/remove syntax is commonly used to "forward" an event implementation to another class.
Cleaning up subscriptions (not "event handles") is best done by implementing IDisposable.
UPDATE: There is some variation on which object should implement IDisposable. The Rx team made the best decision from a design perspective: subscriptions themselves are IDisposable. Regular .NET events do not have an object that represents the subscription, so the choice is between the publisher (the class on which the event is defined) and the subscriber (usually the class that contains the member function being subscribed). While my design instincts prefer making the subscriber IDisposable, most real-world code makes the publisher IDisposable: it's an easier implementation, and there may be cases where there isn't an actual subscriber instance.
(That is, if the code actually cleans up event subscriptions at all. Most code does not.)

C#: events or an observer interface? Pros/cons?

I've got the following (simplified):
interface IFindFilesObserver
{
void OnFoundFile(FileInfo fileInfo);
void OnFoundDirectory(DirectoryInfo directoryInfo);
}
class FindFiles
{
IFindFilesObserver _observer;
// ...
}
...and I'm conflicted. This is basically what I would have written in C++, but C# has events. Should I change the code to use events, or should I leave it alone?
What are the advantages or disadvantages of events over a traditional observer interface?
Consider an event to be a callback interface where the interface has only one method.
Only hook events you need
With events, you only need to implement handlers for events you're interested in handling. In the observer interface pattern, you'd have to implement all methods in the entire interface including implementing method bodies for notification types you don't actually care about handling. In your example, you always have to implement OnFoundDirectory and OnFoundFile, even if you only care about one of these events.
Less maintenance
Another good thing about events is you can add a new one to a particular class so that it will raise it, and you don't have to change every existing observer. Whereas if you want to add a new method to an interface, you have to go around every class that already implements that interface and implement the new method in all of them. With an event though, you only need to alter existing classes that actually want to do something in response to the new event you're adding.
The pattern is built into the language so everybody knows how to use it
Events are idiomatic, in that when you see an event, you know how to use it. With an observer interface, people often implement different ways of registering to receive notifications and hook up the observer.. with events though, once you've learnt how to register and use one (with the += operator), the rest are all the same.
Pros for interfaces
I haven't got many pros for interfaces. I guess they force someone to implement all methods in the interface. But, you can't really force somebody to implement all those methods correctly, so I don't think there's a lot of value on this.
Syntax
Some people don't like the way you have to declare a delegate type for each event. Also, standard event handlers in the .NET framework have these parameters: (object sender, EventArgs args). As sender doesn't specify a particular type, you have to down-cast if you want to use it. This often is fine in practice, it feels not quite right though because you're losing the protection of the static type system. But, if you implement your own events and don't follow the .NET framework convention on this, you can use the correct type so potential down-casting isn't required.
Hmm, events can be used to implement the Observer pattern. In fact, using events can be regarded as another implementation of the observer-pattern imho.
Events are harder to propagate through chain of objects, for example if you use FACADE pattern or delegate work to other class.
You need to be very careful with unsubscribing from events to allow object to be garbage collected.
Events are 2x time slower than simple function call, 3x slower if you do null check on every raise, and copy event delegate before null check and invocation to make it thread safe.
Also read MSDN about new (in 4.0) IObserver<T> interface.
Consider this example:
using System;
namespace Example
{
//Observer
public class SomeFacade
{
public void DoSomeWork(IObserver notificationObject)
{
Worker worker = new Worker(notificationObject);
worker.DoWork();
}
}
public class Worker
{
private readonly IObserver _notificationObject;
public Worker(IObserver notificationObject)
{
_notificationObject = notificationObject;
}
public void DoWork()
{
//...
_notificationObject.Progress(100);
_notificationObject.Done();
}
}
public interface IObserver
{
void Done();
void Progress(int amount);
}
//Events
public class SomeFacadeWithEvents
{
public event Action Done;
public event Action<int> Progress;
private void RaiseDone()
{
if (Done != null) Done();
}
private void RaiseProgress(int amount)
{
if (Progress != null) Progress(amount);
}
public void DoSomeWork()
{
WorkerWithEvents worker = new WorkerWithEvents();
worker.Done += RaiseDone;
worker.Progress += RaiseProgress;
worker.DoWork();
//Also we neede to unsubscribe...
worker.Done -= RaiseDone;
worker.Progress -= RaiseProgress;
}
}
public class WorkerWithEvents
{
public event Action Done;
public event Action<int> Progress;
public void DoWork()
{
//...
Progress(100);
Done();
}
}
}
Pros of an interface-solution:
If you add methods, existing observers needs to implement those methods. This means that you have less of a chance of forgetting to wire up existing observers to new functionality. You can of course implement them as empty methods which means you have the luxury of still doing nothing in response to certain "events". But you won't so easily forget.
If you use explicit implementation, you'll also get compiler errors the other way, if you remove or change existing interfaces, then observers implementing them will stop compiling.
Cons:
More thought has to go into planning, since a change in the observer interface might enforce changes all over your solution, which might require different planning. Since a simple event is optional, little or no other code has to change unless that other code should react to the event.
Some further benefits of events.
You get proper multicast behaviour for free.
If you change the subscribers of an event in response to that event the behaviour is well defined
They can be introspected (reflected) easily and consistently
Tool chain support for events (simply because they are the idiom in .net)
You get the option to use the asynchronous apis it provides
You can achieve all of these (except the tool chain) yourself but it's surprisingly hard. For example:
If you use a member variable like a List<> to store the list of observers.
If you use foreach to iterate over it then any attempt to add or remove a subscriber within one of the OnFoo() method callbacks will trigger an exception unless you write further code to deal with it cleanly.
The best way to decide is this: which one suits the situation better. That might sound like a silly or unhelpful answer, but I don't think you should regard one or the other as the "proper" solution.
We can throw a hundred tips at you. Events are best when the observer is expected to listen for arbitrary events. An interface is best when the observer is expected to listed to all of a given set of events. Events are best when dealing with GUI apps. Interfaces consume less memory (a single pointer for multiple events). Yadda yadda yadda. A bulleted list of pros and cons is something to think about, but not a definitive answer. What you really need to do is try both of them in actual applications and get a good feel for them. Then you can choose the one that suits the situation better. Learn form doing.
If you have to use a single defining question, then ask yourself which better describes your situation: A set of loosely related events any of which may be used or ignored, or a set of closely related events which will all generally need to be handled by one observer. But then, I'm just describing the event model and interface model, so I'm back at square one: which one suits the situation better?
Pros are that events are more 'dot-netty'. If you are designing non-visual components that can be dropped onto a form, you can hook them up using the designer.
Cons are that an event only signifies a single event - you need a separate event for each 'thing' that you want to notify the observer about. This doesn't really have much practical impact except that each observed object would need to hold a reference for every observer for every event, bloating memory in the case where there are lots of observed objects (one of the reasons they made a different way of managing the observer/observable relationship in WPF).
In your case I'd argue it doesn't make much difference. If the observer would typically be interested in all those events, use an observer interface rather than separate events.
I prefer an event base solution for the following reasons
It reduces the cost of entry. It's much easier to say "+= new EventHandler" than to implement a full fledged interface.
It reduces maintenance costs. If you add a new event into your class that's all that needs to be done. If you add a new event to an interface you must update every single consumer in your code base. Or define an entirely new interface which over time gets annoying to consumers "Do I implement IRandomEvent2 or IRandomEvent5?"
Events allow for handlers to be non-class based (ie a static method somewhere). There is no functional reason to force all event handlers to be an instance member
Grouping a bunch of events into an interface is making an assumption about how the events are used (and it's just that, an assumption)
Interfaces offer no real advantage over a raw event.
Java has language support for anonymous interfaces, so callback interfaces are the thing to use in Java.
C# has support for anonymous delegates - lambdas - and so events are the thing to use in C#.
A benefit of interfaces is that they are easier to apply decorators to. The standard example:
subject.RegisterObserver(new LoggingObserver(myRealObserver));
compared to:
subject.AnEvent += (sender, args) => { LogTheEvent(); realEventHandler(sender, args); };
(I'm a big fan of the decorator pattern).
If your objects will need to be serialized in some way that retains references such as with NetDataContractSerializer or perhaps protobuf events will not be able to cross the serialization boundary. Since observer pattern relies on nothing more than just object references, it can work with this type of serialization with no problem if that is what is desired.
Ex. You have a bunch of business objects that link to each other bidirectionally that you need to pass to a web service.

Categories