When are anonymous delegates removed from events? - c#

If I write something like
myDataModel.ContentLoaded += (o,e) => { DoSomething(); }
When (if ever) is that anonymous delegate removed from the event?
As a quick example, I could write this program
class Program
{
public event EventHandler<EventArgs> MyEvent = delegate { };
static void Main(string[] args)
{
Program p = new Program();
while(true)
{
p.MyEvent += (o, e) => Console.WriteLine("Hello!");
Console.ReadLine();
p.Foo();
}
}
void Foo()
{
MyEvent(this, EventArgs.Empty);
}
}
And the output as I press 'Enter' repeatedly is
Hello!
Hello!
Hello!
Hello!
Hello!
Hello!
Hello!
Hello!
Hello!
Hello!
...and so forth. I could add the line
p.MyEvent -= (o, e) => Console.WriteLine("Hello!");
after p.Foo() but of course it has no effect because I'm removing an entirely different anonymous delegate.
So what's the deal with this? Is there any way of removing these anonymous delegates at all? What are the implications for, say, an asynchronous Silverlight application where I'm pulling data using expressions like
_myDataContext.Load(myQuery, loadOperation =>
{
// do stuff with the data here
}, null);
? I assume that these kinds of callbacks aren't implemented using events, but of course it's impossible(?) to tell.
Are anonymous delegates dangerous if not carefully accounted for?

There is no (easy) way to remove delegates that you didn't first assing to any variable. It doesn't really matter whether they're anonymous or not. You can assign anonymous delegate to a variable and remove it later:
EventHandler eh = (src, e) => Console.WriteLine("Hello");
form.Click += eh;
// At some later point
form.Click -= eh;
Similarly, there is no (easy) way to remove delegate if you register it using:
form.Click += new EventHandler(foo);
The problem with events is that they are only garbage collected when the object that they're attached to is garbage collected (even if the target object that they work with is not referenced from any other part of program and so they cannot do any useful work).
This can be solved using weak events. Instead of removing them explicitly, you use some mechanims that allows GC to deal with them automatically.

It will never be automatically removed from the event.
If you want to unsubscribe an anonymous delegate, check out this question:
Unsubscribe anonymous method in C#

Related

what does this line means? Can somebody help me by explaining consumer.Received += (model, ea)

this is snip of code. I m not getting "consumer.Received += (model ,ea) =>
As of the docs Received is an event within the EventingBasicConsumer-class. This means that you can register for the event by adding an event-handler to it.
consumer.Recieved += (model, args) => { /*
do whatever you want when the event is triggered
*/};
This is some portion of code (more accurate a delegate) that is executed when the event occurs. In your special case you also get some arguments from the event to appropriately react on that event. The first is of type IBasicConsumer and the second of type BasicDeliverEventArgs. Thus the following is identical to the code I´ve written above:
consumer.Recieved += (IBasicConsumer model, BasicDeliverEventArgs args) => { /*
do whatever you want when the event is triggered
*/};
While you often can omit the first one as it´s not needed the second one holds information the caller of the event (the Rabbit-framework in your case) applied to that delegate. So you can use it and display it in a MessageBox for instance.
var body = args.Body;
Alternativly to using an anonymous method (a method without a name as shown above) you can surely use a named one:
consumer.Recieved += MyHandler;
private void MyHandler(IBasicConsumer model, BasicDeliverEventArgs args)
{
// your stuff here
}
Doing so has the advantage that you can easily remove the handler.
consumer.Recieved -= MyHandler;
So your question boils down to what does consumer.Received += (model, ea) => {stuff} do? Its a Lambda function..
well the Received is an event, which clearly has 2 properties, for which the coder has named them model and ea. Which they they use in {stuff}
Previously you could/would have written (and Im making up variable types here but)
consume.Received += mycall;
void mycall(String model, Mything ea)
{
stuff;
}
There are however disadvantages of the lamda, while you can add them on the fly, its not so easy to remove.. where as the older style you can do consume.Received -= mycall;

Best option for event subscription

Can you tell me which is the best way to create an event or all the options are good?
// OPTION 1
buttonAlert.Click += delegate
{
textChange.Text = string.Format("Hello World");
};
// OPTION 2
buttonAlert.Click +=(sender, e) =>
{
textChange.Text = string.Format("Hello World");
};
// OPTION 3
buttonAlert.Click += delegate (object sender, EventArgs e)
{
textChange.Text = string.Format("Hello World");
};
Its just a matter of preference. In terms of performance are all equivalent.
So, choose based on what you need and prefer.
As a complement of my answer i like to alert that you must unsubscribe a event (-=) after subscrive (+=).
From the documentation:
To prevent your event handler from being invoked when the event is
raised, simply unsubscribe from the event. In order to prevent
resource leaks, it is important to unsubscribe from events before you
dispose of a subscriber object. Until you unsubscribe from an event,
the multicast delegate that underlies the event in the publishing
object has a reference to the delegate that encapsulates the
subscriber's event handler. As long as the publishing object holds
that reference, your subscriber object will not be garbage collected.
I would say that first option is the best when you don´t need the lambda parameters (sender, event).
Between second and third I would choose second because it´s cleaner (just a matter of preference.
You can also use a method as a delegate, and it´s probably the best if you want to manage memory correctly. When you use a delegate or lambda there is no way to unsubscribe. That means that even if you destroy or leave the activity/fragment, the object will remain in memory and the garbage collector won´t be able to clear it. In the case the user opens and closes this screen many times, you may get an OutOfMemoryException eventually. This happens very often in Android. This would be the solution:
protected override void OnResume()
{
base.OnResume();
buttonAlert.Click += OnButtonClick;
}
protected override void OnPause()
{
base.OnPause();
buttonAlert.Click -= OnButtonClick;
}
private void OnButtonClick(object sender, EventArgs e)
{
textChange.Text = string.Format("Hello World");
}

I don't understand the difference between pure delegate and event fields

Delegate : I understand. But when I move to event, many things I don't understand so much. I read book, MSDN and some simple examples on Network, they both have same structures. For example, here is the link : Event Example
I take the first example, that the author said it's the most easiest example about C# Event.
Here is his code :
public class Metronome
{
public event TickHandler Tick;
public EventArgs e = null;
public delegate void TickHandler(Metronome m, EventArgs e);
public void Start()
{
while (true)
{
System.Threading.Thread.Sleep(3000);
if (Tick != null)
{
Tick(this, e);
}
}
}
}
public class Listener
{
public void Subscribe(Metronome m)
{
m.Tick += new Metronome.TickHandler(HeardIt);
}
private void HeardIt(Metronome m, EventArgs e)
{
System.Console.WriteLine("HEARD IT");
}
}
class Test
{
static void Main()
{
Metronome m = new Metronome();
Listener l = new Listener();
l.Subscribe(m);
m.Start();
}
}
You can notice line: public event TickHandler Tick. When I change to public TickHandler Tick, program still run the same. But new line I understand because it's just a pure delegate.
So, my question is : what is the real purpose of event keyword in line : public event TickHandler Tick. This is very important, because all examples always use like this, but I cannot explain why.
Thanks :)
Delegates and events are related concepts, but they are not the same thing. The term "delegate" tends to have two meanings (often glossed over):
A delegate type which is similar to a single method interface. (There are significant differences, but that's a reasonable starting point.)
An instance of that type, often created via a method group, such that when the delegate is "invoked", the method is called.
An event is neither of those. It's a kind of member in a type - a pair of add/remove methods, taking a delegate to subscribe to or unsubscribe from the event. The add and remove methods are used when you use foo.SomeEvent += handler; or foo.SomeEvent -= handler;.
This is very similar to how a property is really a pair of get/set methods (or possibly just one of the two).
When you declare a field-like event like this:
public event TickHandler Tick;
the compiler adds members to your class which are somewhat like this:
private TickHandler tick;
public event TickHandler
{
add { tick += value; }
remove { tick -= value; }
}
It's a bit more complicated than that, but that's the basic idea - it's a simple implementation of the event, just like an automatically implemented property. From inside the class, you can access the backing field, whereas outside the class you'll always end up just using the event.
Personally I think it's a pity that the declaration of a field-like event looks so much like a field of a delegate type - it leads to some of the misleading (IMO) statements found in some of the answers, as if the event keyword "modifies" a field declaration - when actually it means you're declaring something entirely different. I think it would have been clearer if field-like events looked more like automatically-implemented properties, e.g.
// Not real C#, but I wish it were...
public event TickHandler Tick { add; remove; }
I have a whole article going into rather more detail, which you may find useful.
The event keyword basically restricts the operation on your delegate.
You can no longer assign it manually using the = operator.
You can only add (using +=) or remove (using -=) delegates from your event, one by one. This is done in order to prevent some subscriber to "overwrite" other subscriptions.
Consequently, you cannot do: m.Tick = new Metronome.TickHandler(HeardIt)
"event" is a modifier. What's the benefit?
you can use events in interfaces
only the class declaring it can invoke an event
events expose an add and remove accessor that you can override and do custom stuff
events limit you to a specific signature of the assigned method SomeMethod(object source, EventArgs args) which provide you with additional information about the event.
You're correct - the addition of the event keyword seems to be almost redundant. However, there's a key difference between fields that are events and fields that are typed to a pure delegate. Using the event keyword means that objects external to the containing object can subscribe to the delegate, but they cannot invoke it. When you drop the event keyword, external objects can subscribe AND invoke the delegate (visibility permitting.)
When you add a listener to your program you add the event, not the delegate
see your code m.Tick +=
you see that part right there is you are asking for the property (type event) and you are adding to it a listener with the +=. Now you can only add to that Tick property a TickHandler type and if you override it you have to make your own that is the same format as TickHandler.
much like when you add to a string, or int.
string stringTest = string.Empty;
stringTest += "this works";
stringTest += 4; //this doesn't though
int intTest = 0;
intTest += 1; //works because the type is the same
intTest += "This doesn't work";
Metronome m = new Metronome();
Metronome.TickHandler myTicker = new Metronome.TickHandler(function);
m.Tick += myTicker; //works because it is the right type
m.Tick += 4; //doesn't work... wrong type
m.Tick += "This doesnt work either"; //string type is not TickHandler type
does that clear it up some?
As far as i'm informed an event is basically a multicast delegate, but with different access rules for the basic operations, that can be performed on delegates and events from within or outside the class they are defined in.
The operations are:
assign using the = operator
add/remove using the += and -= operator
invoke using the () operator
Operation | delegate | event
------------------+------------+--------
Inside class += / -= | valid | valid
------------------+------------+--------
Inside class = | valid | valid
------------------+------------+--------
Inside class () | valid | valid
------------------+------------+--------
Outside class += / -= | valid | valid
------------------+------------+--------
Outside class = | valid | not valid
------------------+------------+--------
Outside class () | valid | not valid
This gives you encapsulation which is always good OOP style. :-)
I think the main difference between using delegate and event is that the event can be only raised by the Server (means the author of the class)
If you remove the event keyword now you can raise the m.Tick(sender,e) in the Listener otherwise not.
public class Listener
{
public void Subscribe(Metronome m)
{
m.Tick += new Metronome.TickHandler(HeardIt);
}
private void RaisTick(object sender, EventArgs e)
{
m.Tick(sender,e);
}
private void HeardIt(Metronome m, EventArgs e)
{
System.Console.WriteLine("HEARD IT");
}
}

What's the benefits of registering an event handler implicitly

What's the benefits of registering an event as:
void MyMethod()
{
button1.Click += delegate (object sender, EventArgs e)
{
..
}
}
in comparison with:
void MyMethod()
{
button1.Click += new System.EventHandler(this.button1_Click);
}
void button1_Click(object sender, EventArgs e)
{
..
}
UPDATE:
And what about unsubscribing it?
The benefit is that you don't have to come up with a name and a place in your class.
For a light function, tightly coupled to the code that register the event, the short version is more convenient.
Note that you can also exchange delegate for a =>
button1.Click += (object sender, EventArgs e) =>
{
..
}
You can be even more concise:
button1.Click += ( sender, e ) =>
{
};
Syntactically it's cleaner (as long as it doesn't lead to long blocks of code which would be better broken up into named methods).
The inline declaration is a closure, which gives you access to the variables adjacent to the anonymous method.
From: What are 'closures' in .NET?
In essence, a closure is a block of code which can be executed at a
later time, but which maintains the environment in which it was first
created - i.e. it can still use the local variables etc of the method
which created it, even after that method has finished executing.
See also: http://csharpindepth.com/articles/chapter5/closures.aspx
When registering event handler with an anonymous delegate or lambda, you can write shorter code and use closures. But you cannot unsubscribe from the event, and if the event handler code is too long, your code becomes ugly.
It's just about coding style.
Worth mantioning that declaring it like in first case let you to avoid "spaghetti code" and inject into the handler function local variables (if needed) in more natural(human readable way).
To be more clear. By writing like in first case you can:
int x = 0;
System.Windows.Forms.Button button = new System.Windows.Forms.Button();
button.Click += (o,e)=> {
++x;
};
Inside the event handler you can access the local variable declared actually out for the scope of the handler method. For most people it seems "natural", but if you think like a developer it shouldn't be even possible.
Good luck.

what is += (o, arg) => actually achieving?

Sorry to ask all, but I'm an old hand Vb.net guy who's transferring to c#. I have the following piece of code that seems to activate when the (in this case) postAsync method is fired. I just don;t understand what the code is doing (as follows):-
app.PostCompleted +=
(o, args) =>
{
if (args.Error == null)
{
MessageBox.Show("Picture posted to wall successfully.");
}
else
{
MessageBox.Show(args.Error.Message);
}
};
if anyone could explain what the += (o,args) => is actually acheiving I'd be so greatful....
many thanks in advance.
Tim
(o,args) => defines a lambda expression that takes two parameters named o and args. The types of those parameters is inferred according to the type of PostCompleted (if PostCompleted is an EventHandler, then they will be respectively of type Object and EventArgs). The expression's body then follows after the =>.
The result is than added as an handler to PostCompleted.
As such, it's a less verbose way to write:
app.PostCompleted += delegate(object o, EventArgs args)
{
// ...
};
Which is a shorthand for:
void YourHandler(object o, EventArgs args)
{
// ...
}
// ...
app.PostCompleted += YourHandler;
That is an added handler for the PostCompleted event using a lambda expression. It is similar to
app.PostCompleted += MyHandler;
// ...
private void MyHandler(object sender, EventArgs e) {
// ...
}
But when using lambda expressions, you can't detach the handler easily.
It's shorthand for a delegate defining the event handler for the POST completion event:
app.PostCompleted += delegate(object o, EventArgs args) {
// ...
};
See also Anonymous Methods.
Assuming PostCompleted is an event, you are basically creating an event handler using lambda notation.
This code snipped is equivalent to:
app.PostCompleted += delegate (o, args)
{
if (args.Error == null)
{
MessageBox.Show("Picture posted to wall successfully.");
}
else
{
MessageBox.Show(args.Error.Message);
}
};
The vb.net equivalent would look like this:
AddHandler app.PostCompleted, Function(o, args)
''# ...
End Function
Note that this requires Visual Studio 2010/.Net 4, but the C# code works back in Visual Studio 2008/.Net 3.5.
But that's only partly true. In C#, this is a way to define a method as an event handler in one place. In VB.Net, you can use the Handles keyword, and so the actual equivalent might look more like this:
Public Sub App_PostCompleted(ByVal Sender as Object, ByVall e As EventArgs) Handles app.PostCompleted
''#
End Sub
But even that's not completely equivalent, since you gave the method a name and can call it from anywhere. The only reference to the C# code (and thus the only way to call it) is through the event subscription.
The (o,args) => part is a lambda expression, which is an anonymous function.
the += part assigns the lambda expression to be called when the event fires.

Categories