method subscription vs lambda delegate subscription - Which and why? - c#

I have seen some people leaning on handing methods to callbacks/events and then sometimes just handing them lambdas.
Can anybody speak to any difference between the two? I would have originally thought them to be the same, but the inconsistency I have seen implemented sometimes makes me wonder if there is a case where one is preferable over the other? Obviously if there is a very large ammount of code it shouldn't be an on the spot lambda, but otherwise..
Can you all outline any differences between the two if any, and outline the rules you use in choosing between the two when both are available?

One of the biggest differences between the two is the ease by which you can unsubscribe from the event. With the method based approach unsubscribing is a simple operation, simply use the original method
m_button.Click += OnButtonClick;
...
m_button.Click -= OnButtonClick;
With lambdas this is not as simple. You must store away the lambda expression and to be used later on to unsbuscribe from the event
m_button.Click += delegate { Console.Write("here"); }
...
// Fail
m_button.Click -= delegate { Console.Write("here"); }
EventHandler del = delegate { Console.Write("here"); }
m_button.Click += del;
...
m_button.Click -= del;
It really detracts from the convenience of using lambda expressions.

In most languages that have lambdas (including C#), creating a lambda inside a method creates a closure -- that is, the local variables inside the declaring method will be visible to the lambda. That's the biggest difference i'm aware of.
Aside from that, unless you name your event handler somehow, in a way that's accessible in another function, you'll find it hard to detach the event handler later. This is doable by storing the delegate in an instance- or class-level variable, but it can be kinda ugly.

The biggest reason for using a Lambda is to have delayed execution, i.e. you define the operations you want to perform, but you won't have the parameters until later. You generally don't use lambdas for events and callbacks; you use anonymous methods.
Using anonymous methods for events and callbacks is okay for simple events that you don't need to unsubscribe to. The biggest determining factor for me is where I'm declaring it. I'm not going to declare an event handler for a form as an anonymous method, but if I have a short-lived need to connect to an event, it might be okay.
In general, I use actual methods for callbacks and events more than anonymous methods; the events I'm handling are tied to the lifetime of the object, not the lifetime of the method, and I find that it's clearer in code to have callbacks clearly defined external to the function that hooks them up. Some of that is personal preference.

In most cases, there is little practical difference. Which one to use is mainly a matter of personal preference (i.e. what you want the code to look like). In some cases, there are some practical reasons to prefer one over the other:
As noted in the accepted answer, unsubscribing an anonymous method is more complex than unsubscribing a named method. Without a name, there's no way to refer to the anonymous method except by the delegate instance created at runtime where the anonymous method is declared. Using a named method, the delegate can be unsubscribed without having retained a reference to the original delegate (or its equivalent).
On the other hand, a reason to prefer a lambda expression is when the handler for the event is an implementation detail unique to the named method in which the lambda/anonymous method is declared. This can help keep such implementation details private and local to the method where they are used.
Another reason one might use a lambda expression is if there's a need to "adapt" the delegate type. I.e. you do want to call a named method to handle the event, but that method has a different signature than that required by the event. This might be the case where you want to reuse the method for different events or other situations, where some of the parameters from the event might not be applicable. Another case might be where you want to introduce a new parameter a value for which the event might not provide (e.g. an index for a collection of objects all having the same event you want to subscribe to).
There is one special case that may sometimes come up, which is the choice of whether to use a named method by itself, or to use an anonymous method that then calls that named method. It is important to note that, in absence of other practical reasons for choosing one over the other, using a named method is marginally more efficient in this particular case, because it removes one method call from the invocation. In practice, you'll probably never notice the difference, but it's just overhead so if there's no specific, practical reason to incur it, one should probably avoid it, i.e. subscribe the named method directly.

Related

Is having default event initializer considered a good practice?

One thing that I find slightly annoying is having to null-check events. An event that has no subscribers is going to be null, so often times code like this has to be written:
MyEvent?.Invoke()
One solution for this problem I've found was this initialization pattern, where we initialize event with a no-op delegate:
public event Action MyEvent = delegate { };
Now, since this event is always going to have at least one dummy subscriber, we no longer have to check for null:
MyEvent.Invoke()
While this is pretty convenient, I was wondering whether this pattern a good practice, or is there some reason that I don't see that would make this a bad decision (aside from having to call an extra dummy subscriber, but I am fine with that)? Thanks.

Triple delegate

I have a problem where the default delegate does not do enough in some cases. It needs a preamble and a postable. I'm just wondering whether it is better to call a triple delegate
CSELib.ELib eventLib = new CSELib.ELib();
eventLib.Bomb += BombCatcherStart;
eventLib.Bomb += eventLib.BombCatcher;
eventLib.Bomb += BombCatcherEnd;
...
eventLib.BombRaise();
or to call one delegate which then calls the three
void BombCatcherGroup(CSELib.Elib self)
{
BombCatcherStart(self);
self.BombCatcher(self);
BombCatcherEnd(self);
}
CSELib.ELib eventLib = new CSELib.ELib();
eventLib.Bomb += BombCatcherGroup;
...
eventLib.BombRaise();
It basically does the same thing but I just wondering as far as "best practice" is concerned, whether it is better to tell everyone up front as in the triple delegate or to hide it as in in the single delegate.
In the scenario where your operations form a logical chain there aren't really any pros to adding them as individual handlers to the same event - other than that those handlers can be removed down the track. If you don't need/want that, you're incurring the entirely avoidable (if negligible in most scenarios) overhead of additional delegate invocations and losing at least some of the ability to control execution flow. What happens if BombCatcher throws an exception? Easy to handle if all your operations are part of the same method definition; not so easy if you're dealing with separate delegates.

Automatically calling method after code block

I'm adding the notion of actions that are repeatable after a set time interval in my game.
I have a class that manages whether a given action can be performed.
Callers query whether they can perform the action by calling CanDoAction, then if so, perform the action and record that they've done the action with MarkActionDone.
if (WorldManager.CanDoAction(playerControlComponent.CreateBulletActionId))
{
// Do the action
WorldManager.MarkActionDone(playerControlComponent.CreateBulletActionId);
}
Obviously this could be error prone, as you could forget to call MarkActionDone, or possibly you could forget to call CanDoAction to check.
Ideally I want to keep a similar interface, not having to pass around Action's or anything like that as I'm running on the Xbox and would prefer to avoid passing actions around and invoking them. Particularly as there would have to be a lot of closures involved as the actions are typically dependent on surrounding code.
I was thinking of somehow (ab)using the IDisposeable interface, as that would ensure the MarkActionDone could be called at the end, however i don't think i can skip the using block if CanDoAction would be false.
Any ideas?
My preferred approach would be to keep this logic as an implementation detail of WorldManager (since that defines the rules about whether an action can be performed), using a delegate pattern:
public class WorldManager
{
public bool TryDoAction(ActionId actionId, Action action)
{
if (!this.CanDoAction(actionId)) return false;
try
{
action();
return true;
}
finally
{
this.MarkActionDone(actionId);
}
}
private bool CanDoAction(ActionId actionId) { ... }
private void MarkActionDone(ActionId actionId) { ... }
}
This seems to fit best with SOLID principals, since it avoids any other class having to 'know' about the 'CanDoAction', 'MarkActionDone' implementation detail of WorldManager.
Update
Using an AOP framework, such as PostSharp, may be a good choice to ensure this aspect is added to all necessary code blocks in a clean manner.
If you want to minimize GC pressure, I would suggest using interfaces rather than delegates. If you use IDisposable, you can't avoid having Dispose called, but you could have the IDisposable implementation use a flag to indicate that the Dispose method shouldn't do anything. Beyond the fact that delegates have some built-in language support, there isn't really anything they can do that interfaces cannot, but interfaces offer two advantages over delegates:
Using a delegate which is bound to some data will generally require creating a heap object for the data and a second for the delegate itself. Interfaces don't require that second heap instance.
In circumstances where one can use generic types which are constrained to an interface, instead of using interface types directly, one may be able to avoid creating any heap instances, as explained below (since back-tick formatting doesn't work in list items). A struct that combines a delegate to a static method along with data to be consumed by that method can behave much like a delegate, without requiring a heap allocation.
One caveat with the second approach: Although avoiding GC pressure is a good thing, the second approach may end up creating a very large number of types at run-time. The number of types created will in most cases be bounded, but there are circumstances where it could increase without bound. I'm not sure if there would any convenient way to determine the full set of types that could be produced by a program in cases where static analysis would be sufficient (in the general case, where static analysis does not suffice, determining whether any particular run-time type would get produced would be equivalent to the Halting Problem, but just as many programs can in practice be statically determined to always halt or never halt, I would expect that in practice one could often identify a closed set of types that a program could produce at run-time).
Edit
The formatting in point #2 above was messed up. Here's the explanation, cleaned up.
Define a type ConditionalCleaner<T> : IDisposable, which holds an instance of T and an Action<T> (both supplied in the constructor--probably with the Action<T> as the first parameter). In the IDisposable.Dispose() method, if the Action<T> is non-null, invoke it on the T. In a SkipDispose() method, null out the Action<T>. For convenience, you may want to also define ConditionalCleaner<T,U>: IDisposable similarly (perhaps three- and four-argument versions as well), and you may want to define a static class ConditionalCleaner with generic Create<T>, Create<T,U>, etc. methods (so one could say e.g. using (var cc = ConditionalCleaner.Create(Console.WriteLine, "ABCDEF") {...} or ConditionalCleaner.Create((x) => {Console.WriteLine(x);}, "ABCDEF") to have the indicated action performed when the using block exits. The biggest requirement if one uses a Lambda expression is to ensure that the lambda expression doesn't close over any local variables or parameters from the calling function; anything the calling function wants to pass to the lambda expression must be an explicit parameter thereof. Otherwise the system will define a class object to hold any closed-over variables, as well as a new delegate pointing to it.

Parallel EventHandler

I want to notify my class's event subscribers without delay and simultaneously.
Should I roll my own event handler; use some from FCL supporting parallelism; or default built-in System.EventHandler<T> support such way of event notification?
You can use MulticastDelegate.GetInvocationList for any delegate, and then just invoke all of the component delegates in parallel. That's probably the easiest way to go.
(It returns Delegate[] but you can cast each instance to the right type. You may even get away with casting the array itself - I can't remember exactly what kind of array it actually creates.)

When to use callbacks instead of events in c#?

When would you favour using a callback (i.e, passing in a Func or Action), as opposed to exposing and using an event?
UPDATE
What motivated this question was the following problem:
I have a ThingsHandler class, which
can be associated with a ThingEditor.
The ThingsHandler handles a list of
Things, knows their order, which one is 'current', when new
ones are added or deleted etc.
The ThingEditors can just modify a single
thing.
The ThingsHandler needs to alert
the ThingEditor when the user selects
a new Thing to edit, and the
ThingEditor needs to alert the
ThingsHandler when the user says
'done'.
What bothers me is having these two classes holding references to each other - though I guess that's inevitable - or binding to events in both directions. I wondered if using a callback in one direction was 'cleaner'.
I suspect there is a design pattern for this.
Though the other answers thus far seem reasonable, I would take a more philosophical tack.
A class is a mechanism that models a particular kind of thing in a particular domain. It is very easy when writing the internal details of a class to conflate the implementation details of the mechanism with the semantics being modeled. A brief example of what I mean:
class Giraffe : Mammal, IDisposable
{
public override void Eat(Food f) { ... }
public void Dispose() { ... }
}
Notice how we've conflated the real-world thing being modeled (a giraffe is a kind of mammal, a giraffe eats food) with the details of the implementation (an instance of Giraffe is an object which can be disposed of with the "using" statement). I guarantee that if you go to the zoo, you will never see a giraffe being disposed of with the using statement. We've mixed up the levels here, which is unfortunate.
I try to use events (and properties) as part of the semantic model and use callback methods (and fields) as part of the mechanism. I would make GaveBirth an event of Giraffe, since that is part of the model of real-world giraffe behaviour we're attempting to capture. If I had some mechanism, like, say I wanted to implement an inorder-walk tree traversal algorithm that walked the family tree of giraffes and called a method back on every one, then I'd say that this was clearly a mechanism and not part of the model, and make it a callback rather than try to shoehorn that into the event model.
I use callbacks in a few cases where I know it will only ever fire once, and the callback is specific to a single method call (rather than to an object instance) - for example, as the return part of an async method.
This is particularly true of static utility methods (since you don't have an instance, and static events are deadly when used carelessly, and to be avoided), but of course the other option is to create a class instance with an event instead.
Generally, I use a callback if it is required, whereas an event is used when it should be optional.
Don't expose an event if you're expecting there to always be something listening.
Consider the following:
public class MyClass_Event
{
public event EventHandler MakeMeDoWork;
public void DoWork()
{
if (MakeMeDoWork == null)
throw new Exception("Set the event MakeMeDoWork before calling this method.");
MakeMeDoWork(this, EventArgs.Empty);
}
}
versus:
public class MyClass_Callback
{
public void DoWork(EventHandler callback)
{
if (callback == null)
throw new ArgumentException("Set the callback.", "callback"); // better design
callback(this, EventArgs.Empty);
}
}
The code is almost the same as the callback can be passed as null, but at least the exception thrown can be more relevant.
Callbacks are good when one object wishes to receive a single notification (e.g. an Async data read runs and then calls you with the result).
Events are good for recurring notifications that can be received by an arbitrary number of listeners.
One example is when the callback should return something. E.g. (stupid example):
public int Sum(Func<int> callbackA, Func<int> callbackB) {
return callbackA() + callbackB();
}
public void UseSum() {
return sum(() => 10, () => 20);
}
In terms of OO design and class coupling there isn't great deal of difference between a callback interface and an event.
However, I prefer events where they are things the class needs to "shout about" to whoever is interested in listening (usually multiple things) and callbacks where a specific class has requested an async operation.
Whatever you use, use them consistently across the codebase!
I would use Func or Action when I am going to call the function once or use a Lambda expression.
Events can be registered more than once which sometimes is ideal. With a callback, one has to implement a registration system for the callbacks if you want multiple.
Well, I think they are same things. There're many different tech terms to name the same concepts or things in the different languages.
So, what do you mean "Callback" or "event handler"?
According to MSDN: Callback function is code within a managed application that helps an unmanaged DLL function complete a task.
And, MADN also gives us a introduction of the difference between them.click here
Callbacks are extensibility points that allow a framework to call back into user code through a delegate. These delegates are usually passed to the framework through a parameter of a method.
Events are a special case of callbacks that supports convenient and consistent syntax for supplying the delegate (an event handler). In addition, Visual Studio’s statement completion and designers provide help in using event-based APIs
Also, in some books, such as this book, the author seemed say the same thing with MSDN.
Therefore, in my opinion, you can't say use callbacks instead of events in the C#.

Categories