I want to know can we declare the events as static if yes why and application of such declaration.
Sample please as seeing is believing
You can create static events. You use them the same way as a normal event, except that it's used in a static context within the class.
public class MyClass
{
public static event EventHandler MyEvent;
private static void RaiseEvent()
{
MyEvent?.Invoke(typeof(MyClass), EventArgs.Empty);
}
}
That being said, there are many issues with static events. You must take extra care to unsubscribe your objects from static events, since a subscription to a static event will root your subscribing instance, and prevent the garbage collector from ever collecting it.
Also, I've found that most cases where I'd want to make static events, I tend to learn towards using a standard event on a Singleton instead. This handles the same scenarios as a static event, but is (IMO) more obvious that you're subscribing to a "global" level instance.
Yes, you can. See, for example, Application.ApplicationExit. Note, however, the warnings on that page about memory leaks when attaching to static events; that applies to all static events.
There's nothing magical about when you use them: when you need to provide an event for a static class or an event that deals exclusively with static data and it makes sense to implement it this way.
Yes, you can declare an event as static. You use them the same way you would use them if they were instance events, but you access the event name in a static way (i.e. ClassName.EventName, rather than variableName.EventName).
Now... do you want static events? That's highly debatable. I personally would say no, since static anything creates difficulties in testing and should thus be avoided whenever possible.
But it's certainly possible.
public delegate void SomeEventDelegate();
public class SomeClass
{
public static event SomeEventDelegate SomeEvent;
}
Related
I have a scenario where on application crash, I have to clear certain registry keys. I am trying to use Dispose() pattern for it. in case of application crash during garbage collection does the Dispose gets called to clear the registry???
Is there any other pattern to do such activities? I can not use Unhandled application handler as the code I want to call is not referenced directly by the Main application. I could use reflection but not sure if that's the right pattern.
any advise or experience in this matter will be really appreciated.
It sounds like you want to add an event handler to the AppDomain.UnhandledException event, do some processing (writing to the registry in this case) and then let the program die.
Assuming that you're not doing anything odd like loading your library into a different AppDomain you should be able to hook this from your library in a variety of ways. I've used a static constructor for this in the past and to hook the AssemblyResolve event from a library.
Something like this:
public static class CrashHandler
{
public static bool Initialized { get; private set; }
[SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlAppDomain)]
static CrashHandler()
{
AppDomain.CurrentDomain.UnhandleException += crash_handler;
Initialized = true;
}
static void crash_handler(object sender, UnhandledExceptionEventArgs args)
{
// do your thing here
}
}
In order to get this to actually fire you need to read the Initialized value somewhere at least once. Add it to the constructor of one of your library objects that you can be sure will be instantiated early.
I reuse the code below a lot when I create events that will be used in different areas of an application. I find it really helpful and it makes events very easy to follow in the code. Is there any reason why this could be a bad idea? This is a bit broad, but basically is there a reason not to do this?
Event classes:
public delegate void FocusEventHandler(object source, FocusEventArgs e);
class FocusEvent
{
public static event FocusEventHandler focusEvent;
public static void Focus(bool status)
{
focusEvent(null, new FocusEventArgs(status));
}
}
public class FocusEventArgs : EventArgs
{
public bool Focused { get; set; }
public FocusEventArgs(bool f)
{
Focused = f;
}
}
So to fire the event, all I need is:
FocusEvent.Focus(false);
Thanks guys. This helps a lot. I really need to read up on memory usage.
The single biggest problem with static events is that you need to be really careful about unsubscribing from them. With an instance event, if you don't unsubscribe then you might end up keeping part of a graph artificially alive until the object with the event is released and is unreachable (making all the subscribers unreachable) - however, a static event never becomes unreachable. This means that any subscribers that don't unsubscribe will never be unreachable, and will never be garbage collected.
A few years back, I worked on a large-scale Windows app that used static events. While investigating some memory usage issues, I discovered that no forms in the entire application were ever garbage collected. Pretty much every form subscribed to a static event, but never unsubscribed, causing them to stick around forever.
So yeah, the main reason not to do this is that you'll inevitably forget to unsubscribe from the event at some point, causing things to stick around for the lifetime of the application.
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.
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.)
I use them for "communication" between different objects, as publisher and subscriber pattern.
Is some examples I see that sometimes event is declared as static and sometimes it's not:
public delegate void LogProgress(string str)
public static event LogProgress LogProgressEvent;
if (LogProgressEvent != null)
LogProgressEvent(tempString);
Why and when I need to use static?
Static events are actually quite dangerous, and (fortunately) also quite rare. As with anything static, you would use it when it applies to the type generally, not any specific instance. And even then, you might see it on a singleton instance rather than as a static event.
The danger is that it is ludicrously easy to forget to unsubscribe, and end up keeping masses of objects alive forever; contrast to most instance-based events - usually, the instance will go out-of-scope eventually, making the delegates collectable (a delegate instance will keep a target instance alive).
static applied to events is not different from applying static to any other C# field.
static events are available to callers at any time, even if no instance of the class exists. I guess if you want to raise events from a static method, static events will be useful
See implications of using static events in Marc's answer