Tips in C#
This page is a reminder and how-to for my best tips in C#
Avoid duplication in event subscribers
Sometimes it's useful to strictly control the subscribers of custom events.
To make an example, in my application SyMenu, I have a static helper class (LangHelper) to manage the multilanguage labels. This helper fires an event when user decides to change application language.
The event is declare as static and any object that wants to be notified (the various forms of the application) has to subscribe to it.
LangHelper.TranslateEvent +=
new LangHelper.EventHandlerTranslate(Translate);
|
Forms are always instanced classes, so if I create and quit a certain form several times, it doesn't have memory that it has already loaded a pointer to its own translation method in the LangHelper static method.
The twice or triple subscription doesn't involve a compiler error or a runtime error but cause that delegate method inside the subscriber class is call and recall two or three times. And this is bad.
A solution implementing in dispose or close method of any subscriber class, the explicit code to unsubscribe event, has one big disadvantage: the subscribers have to know the internal structure of LangHelper. On the other hand a solution like that allows the object to be finalize in a correct way because all external reference will be lost.
Only to provide an example I don't care about right finalization and I implement a method to track the subscriber of my static event.
This is the code.
/// <summary>
/// Event handler.
/// </summary>
public static EventHandler _Event;
/// <summary>
/// Events to be notified in case of languages changing.
/// </summary>
public static event EventHandler NoDuplicateSubscriptorsEvent
{
add
{
// check if already loaded
if (_Event != null)
{
List<Delegate> subscribersList =
new List<Delegate>(_Event.GetInvocationList());
if (subscribersList.Exists(delegate(Delegate deleg)
{ return (deleg.Target) == value.Target; }))
return;
}
_Event += value;
}
remove {
_Event -= value;
}
}
|
The event add and remove methods are explicitly declared so I can control the process of adding and removing delegate functions done by subscribers.
The core method resides in lines that check the existence of current subscriber.
The event method GetInvocationList() extracts a Delegate array of subscribers.
I copy array into a list to avoid manual enumeration and to use its Exists method to check the uniqueness of delegate.
Naturally you should implement the overload of equals operator for class whom instances you are comparing because two different instances of the same class are not the same object.
In my case the fast way to check if the two instances are the same is based on form names.
if (subscribersList.Exists(delegate(Delegate deleg)
{return (deleg.Target as Control).Name
== (value.Target as Control).Name; }))
|
Syncerly this is not a great way to compare objects but it works (only to explain)!
So if I don't care about right finalization of objects this is a way to avoid twice subscriptions from the same subscriber.
By the way, in SyMenu I prefer subscribing and unsubscribing every static event from the subscriber form.