Besides not knowing if you attached the handler or not, the problem with anonymous handlers is that you cannot detach them from the event afterwards. With your specific example, if onCallBackDelegate
has the same signature as the event delegate, there is no point in wrapping it in an anonymous method, just attach the delegate directly.
Regarding multiple subscription, depending on what the method actually does, your can either choose to register once (keep in mind this is not safe for multi-threaded access):
// client is making sure that the handler doesn't get
// attached twice
bool _callbackRegistered;
void SomeFunction(Action onCallBackDelegate)
{
if (_callbackRegistered)
return;
_callbackRegistered = true;
SomeClass.OnEvent += onCallBackDelegate;
}
Alternatively, you can check if event's invocation list already contains the delegate, but you can only do this inside the event's parent class, i.e.
class SomeClass
{
private event Action SomeEvent;
// the event is private, and we can only subscribe
// through this method
public void Subscribe(Action callback)
{
// 'callback' already attached?
if (SomeEvent != null && SomeEvent.GetInvocationList().Contains(action))
return;
SomeEvent += callback;
}
public void Unsubscribe(Action callback)
{
SomeEvent -= callback;
}
}
One way also is to detach before you attach the handler, because detaching the handler won't throw an exception if the handler wasn't attached previously:
public void Subscribe(Action callback)
{
// detach if already attached
SomeEvent -= callback;
// attach
SomeEvent += callback;
}
The second pattern might provide a false sense of security, because if you keep attaching anonymous handlers, the Contains
method will fail to detect a duplicate delegate. In other words:
void Handler() { }
// this will subscribe the handler only once:
someClass.Subscribe(Handler);
someClass.Subscribe(Handler);
// this will unsubscribe the handler and leave the invocation list empty
someClass.Unsubscribe(Handler);
// but this will subscribe **both** anonymous handlers:
someClass.Subscribe(() => Handler());
someClass.Subscribe(() => Handler());
// and this won't do anything
someClass.Unsubscribe(() => Handler());
However, both of these patterns are, in my experience, most likely unnecessary. In most cases, you will instantiate a class (which provides some sort of a functionality) and attach to its handler there, only once:
// attach here and forget it
var someClass = new SomeClass();
someClass.OnEvent += Handler;
// once the someClass instance is no longer used, it will get
// collected and there is no need to detach your handler