I am kind of tired of having all this useless noise in my code:
private void RaiseSomeOtherEventIfItIsNotNull()
{
if (this.SomeOtherEvent != null)
{
this.SomeOtherEvent(this, EventArgs.Empty);
}
}
In 99.9% of the cases I don't care if someone attached to it or if it is null or not. Just raise the event! I really don't get it why the c# compiler makes me write all this noise.
So I though I could maybe declare an event like this:
public event EventHandler SomeOtherEvent = delegate { };
this would allow me to get rid of the useless null check and the useless Raise* Method. I could just always do:
this.SomeOtherEvent(this, EventArgs.Empty);
Now when I compare the standard approach with "my" approach in Lutz Röder's Reflector I see some signigicant differences. The compiler has overriden Add{} and Remove{}there is an extra static instance of the anonymous delegate:
[CompilerGenerated]
private static EventHandler CS$<>9__CachedAnonymousMethodDelegate1;
and there is this:
.method private hidebysig static void <.ctor>b__0(object, class [mscorlib]System.EventArgs) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()
.maxstack 8
L_0000: nop
L_0001: ret
}
Now my question: Do you seen any issues or disadvantages in decalring events with a default initialization like this?
You've shown an extra method, but not the extra class. The extra method is fine, IMO - that's just representing the no-op handler. Not a problem.
An extra class is somewhat surprising, as is the idea that it's changing the add/remove behaviour... the compiler would always be creating add/remove methods for the event, as that's what makes it an event.
Personally I think this is fine - but an alternative would be to write extension methods, e.g.
public static void Raise<T>(this EventHandler<T> handler, object sender, T args)
where T : EventArgs
{
if (handler != null)
{
handler(sender, args);
}
}
public static void Raise(this EventHandler handler, object sender,
EventArgs args)
{
if (handler != null)
{
handler(sender, args);
}
}
then just call
myEvent.Raise(this, args);
That will work for all EventHandler and EventHandler<T> events.
The convention used by microsoft is this :
Declare the event like this.
public event EventHandler<ChangedArgs> ItemChanged;
Then create a calling method
protected virtual void OnItemChanged(ChangedArgs args)
{
var handler = ItemChanged;
if (handler != null)
handler(this, args);
}
This also is ThreadSafe and whenever to raise the event, simply call OnItemChanged
As far as I can tell, no, since these are no-op handlers (since the IL generates a nop and a ret instruction). Assigning an empty handler is pretty much the same as having none at all, i.e. you do nothing about that event.
I could be completely wrong (and if so, do tell me why, I'm curious too now), but maybe you need to declare the event delegate at class level?
public delegate void SomeEvent(object sender, EventArgs e);
?
Related
I may be misunderstanding something fundamental here as I'm new to these concepts so please bear with me.
I'm currently removing methods from an event like so:
scheduleView.TouchDown -= scheduleView_TouchDown;
And then on other occasions - adding the methods:
scheduleView.TouchDown += scheduleView_TouchDown;
It all works fine so far, and I can understand it's possible to add several methods, like so:
scheduleView.TouchDown += scheduleView_TouchDown;
scheduleView.TouchDown += scheduleView_AnotherTouchDownEventHandler;
But how would I then later check what methods were wired up to this event?
Interestingly, you can't (at least, from the outside). An event is only obliged to offer 2 accessors - add and remove. There are other accessor methods defined in the CLI spec, but they aren't used in C# or anywhere else AFAIK. The key point: we can't ask an event what is subscribed (and indeed, we shouldn't need to know). All you can do is: add or remove.
If you are worried about double-subscribing, then note that if you try to unsubscribe and you haven't actually subscribed, then under every sane implementation this is simply a no-op; which means you can do:
// make sure we are subscribed once but **only** once
scheduleView.TouchDown -= scheduleView_TouchDown;
scheduleView.TouchDown += scheduleView_TouchDown;
From the perspective of the code raising the event, you rarely need to know who - simply:
// note I'm assuming a "field-like event" implementation here; otherwise,
// change this to refer to the backing-field, or the delegate from the
// event-handler-list
var handler = TouchDown;
if(handler != null) handler(this, EventArgs.Empty); // or similar
There is also a way to break the delegate list into individual subscribers, but it is very rarely needed:
var handler = TouchDown;
if(handler != null) {
foreach(EventHandler subscriber in handler.GetInvocationList()) {
subscriber(this, EventArgs.Empty);
}
}
The main uses for this are:
when you want to perform exception-handling on a per-subscriber basis
when the delegate returns a value or changes state, and you need to handle that on a per-subscriber basis
Yes: If you are within the class that publishes the Event, you can just access the delegate, and you can call the GetInvocationList method to get a list of the subscribers.
No: If you are working outside the class, as the delegate is not exposed to you. You could use reflection to get at it, but that would be a hack, at best.
In the type that declares the event, you can use GetInvocationList() to find out which delegates are subscribed:
public class EventProvider
{
public event EventHandler SomeEvent;
protected virtual void OnSomeEvent(EventArgs args)
{
if (SomeEvent != null)
{
var delegates = SomeEvent.GetInvocationList();
foreach (var del in delegates)
{
Console.WriteLine("{0} has subscribed to SomeEvent", del.Method.Name);
}
SomeEvent(this, args);
}
}
public void RaiseSomeEvent()
{
OnSomeEvent(EventArgs.Empty);
}
}
public class Program
{
public static void Main()
{
EventProvider provider = new EventProvider();
provider.SomeEvent += Callback1;
provider.SomeEvent += Callback2;
provider.RaiseSomeEvent();
}
public static void Callback1(object sender, EventArgs e)
{
Console.WriteLine("Callback 1!");
}
public static void Callback2(object sender, EventArgs e)
{
Console.WriteLine("Callback 2!");
}
}
This produces the following output:
Callback1 has subscribed to SomeEvent
Callback2 has subscribed to SomeEvent
Callback 1!
Callback 2!
I would like to hear opinions on below code snippet. Is there anything that can be improved? Is the event handler/raiser naming following best practices? I know it is not that useful to handle and raise events in the same class but this is just a snippet.
public class MyControl
{
public MyControl()
{
this.LogWritten += this.HandleMyControlLogWritten;
}
// Event handler
void HandleMyControlLogWritten(object sender, EventArgs e)
{
}
// Event object
public event Action<object, EventArgs> LogWritten;
// Event raiser
protected virtual void OnLogWritten(EventArgs e)
{
if (this.LogWritten != null)
{
this.LogWritten(this, e);
}
}
}
The main change I'd recommend would be to get a copy of the event handler:
// Event raiser
protected virtual void OnLogWritten(EventArgs e)
{
var handler = this.LogWritten;
if (handler != null)
{
handler(this, e);
}
}
This is important if you're planning to (eventually) use this class in a multi-threaded scenario. As such, I find that it's a good "best practice" to get into the habit of using. The issue is that, when using in multiple threads, without creating the copy, it's possible that the only "handler" attached could unsubscribe between the null check and the invocation, which would cause a runtime error. By copying to a temporary variable (the var handler = this.LogWritten;) line, you're effectively creating a "snapshot" of the subscriber list, and then checking it for null and invoking if required.
The other change is in the event declaration itself. Instead of using Action<T1,T2>:
// Event object
public event Action<object, EventArgs> LogWritten;
I would recommend using EventHandler<TEventArgs> (if you want to use a custom EventArgs subclass) or EventHandler (for standard EventArgs). These are more "standard practice", and will be what other developers expect:
// Event object
public event EventHandler LogWritten;
When I try to call the event myevent in the function fire, it gives compiler error as
delegate mydelegate does not take 0 arguments.
if i try to give arguments in calling myevent as
myevent(this);
it again shows error as it does not take 1 parameters. what parameters am i supposed to give in the calling myevent? Here's the program code:
namespace useofdelegates
{
public class Class1
{ int i;
public delegate void mydelegate(object sender,EventArgs e);
public event mydelegate myevent;
public void fire()
{
myevent(this); // *** shows compiler error ***
}
}
}
The compiler error is because you are using a delegate with two parameters and calling it with one.
The simple solution is
myevent(this, EventArgs.Empty);
The more regular (and thread-safe) solution, which I think you're getting confused with is
OnMyEvent(EventArgs.Empty);
// and then later
public void OnMyEvent(EventArgs args)
{
mydelegate handler = myevent;
if(handler != null) handler(this, args);
}
The reason for doing it this way is that you should always make sure that there is at least one handler attached to the event. There is a small chance that the handler can be detached between checking for null and calling the handler, so it's good to pass it on to another variable which it cannot be detached from before checking for null.
You need to pass in 2 parameters. the first one being the source of the event. In your example "this" would work. The second one being of type EventArgs or a realted subclass. You can also pass EventArgs.Empty is you do not wish to pass any event especific information to the event handler.
So your method would look like this
fire(this, EventArgs.Empty);
or
fire(this, new MyCustomEVentArgs());
Here is an MSDN link with an example of using events http://msdn.microsoft.com/en-us/library/aa645739(VS.71).aspx
and nother one on creating custom EventArg subclasses to use in your handler. http://www.devarticles.com/c/a/C-Sharp/Creating-Custom-Delegates-and-Events-in-C-sharp/
You have declared mydelegate to require an object and an EventArgs, so you have to pass these in. Of course, you don't have declare your delegate with these arguments. You could just declare it thus:
public delegate void mydelegate();
or just pass this as the sender:
public delegate void mydelegate(object sender);
Just create an empty EventArgs I guess.
myevent(this, new EventArgs());
Note, here is the full code:
namespace useofdelegates
{
public class Class1
{
int i;
public delegate void mydelegate(object sender, EventArgs e);
public event mydelegate myevent;
public void fire()
{
myevent(this, new EventArgs()); // *** shows compiler error ***
}
}
}
On the MSDN, I have found following:
public event EventHandler<MyEventArgs> SampleEvent;
public void DemoEvent(string val)
{
// Copy to a temporary variable to be thread-safe.
EventHandler<MyEventArgs> temp = SampleEvent;
Is it reference?
If so I do not understand its meaning as when SampleEvent became null, so does the temp
if (temp != null)
temp(this, new MyEventArgs(val));
}
This is a paranoia thing to do with threading. If another thread unsubscribes the last handler just after you've checked it for null, it could become null and you'll cause an exception. Since delegates are immutable, capturing a snapshot of the delegate into a variable stops this from happening.
Of course, it does have the other side effect that you could (instead) end up raising the event against an object that thinks it already unsubscribed...
But to stress - this is only an issue when multiple threads are subscribing / unsubscribing to the object, which is a: rare, and b: not exactly desirable.
(From what I read in Essential C# 4.0)
Basically, from this C# code:
public class CustomEventArgs: EventArgs {…}
public delegate void CustomEventHandler(object sender, CustomEventArgs a);
public event CustomEventHandler RaiseCustomEvent;
the compiler will generate CIL code (loosely) equivalent to the following C# code:
public delegate void CustomEventHandler(object sender, CustomEventArgs a);
private CustomEventHandler customEventHandler; // <-- generated by the compiler
public void add_CustomEventHandler(CustomEventHandler handler) {
System.Delegate.Combine(customEventHandler, handler);
}
public void remove_CustomEventHandler(CustomEventHandler handler) {
System.Delegate.Remove(customEventHandler, handler);
}
public event CustomEventHandler customEventHandler {
add { add_customEventHandler(value) }
remove { remove_customEventHandler(value) }
}
When you copy the event, you actually copy the private CustomEventHandler customEventHandler. Since delegate is immutable, the copy won't be affected when the original customEventHandler is modified. You can try this code to see what I mean:
string s1 = "old";
string s2 = s1;
s1 = "new"; // s2 is still "old"
Another important characteristic to note about the generated CIL
code is that the CIL equivalent of the event keyword remains in the CIL.
In other words, an event is something that the CIL code recognizes
explicitly; it is not just a C# construct. By keeping an equivalent event
keyword in the CIL code, all languages and editors are able to provide
special functionality because they can recognize the event as a special
class member.
I guess you were confused mainly because you thought event is a sugar-syntax for a class, right?
I had once a situation where I had to override the event handler in some derived class of mine. I could not unfortunately just "override" it since the implementation logic was bound strictly to that particular method implementation in the base class.
My natural idea was to first "unbind" the original event handler from the event and then to bind my own brand-new method. So I tried to use the "-=" operator like:
myObject.SomeEvent -= new EventHandler (BaseClass.SomeEventHandler)
at which point the compiler complainer that it had no access to the private method SomeEventHandler. Since the base class was a part of the library I did not really want to modify its implementation (though simply as it seems by just turning "private" into "protected");
It's so simple to attach an event handler to an event. Why is it so difficult to get rid of one?
Why I wanted it? Because the base implementation was casing some problems (just did not handle our particular case) so I wanted to redefine it. But even after I attached my event handler the base implementation was getting executed anyway. Since it was doing some kind of Redirect, my own implementation was never going to run since the request processing was being broken at server after redirect.
Is there anyway to get rid of an event handler in a base class from a library without modifying its implementation?
It would be just as easy to get rid of the handler if your code can officially see the handler. If absolutely necessary, it is possible to unsubscribe using reflection to get hold of the delegate, but this is messy. It would be a lot cleaner and safer to either a: avoid the requirement, or b: change the code to make the handler protected.
Reflection approach (use at own risk); uncomment the block in the Bar.ctor() to see the change.
using System;
class Foo
{
public event EventHandler SomeEvent;
public Foo()
{
SomeEvent += SecretHandler; // a bad idea, anyway
//(self-subscribed events....)
}
protected virtual void OnSomeEvent()
{
EventHandler handler = SomeEvent;
if (handler != null) handler(this, EventArgs.Empty);
}
private void SecretHandler(object sender, EventArgs args)
{
Console.WriteLine("suscribed");
}
}
class Bar : Foo
{
public Bar()
{
/*
MethodInfo method = typeof(Foo).GetMethod("SecretHandler",
BindingFlags.NonPublic | BindingFlags.Instance);
EventHandler handler = (EventHandler)Delegate.CreateDelegate(
typeof(EventHandler), this, method);
SomeEvent -= handler;
*/
}
public void Test()
{
OnSomeEvent();
}
}
static class Program
{
static void Main()
{
Bar bar = new Bar();
bar.Test();
}
}