4
\$\begingroup\$

Given a class which is an event dispatcher whose underlying store is a dictionary of events whose key is the event type private readonly Dictionary<Type, Delegate> _applicationEventHandlers;, is this the correct way to remove all remaining delegates when the class needs to be disposed?

 private void RemoveAllListeners()
 {
 foreach (Type handlerType in _applicationEventHandlers.Keys)
 {
 Delegate handlers = _applicationEventHandlers[handlerType];
 Delegate.RemoveAll(handlers, handlers);
 }
 }

Or is there a better way? I have included the whole class below for clarity.

using System;
using System.Collections.Generic;
internal class ApplicationEventDispatcher : IApplicationEventDispatcher, IDisposable
{
 private bool _disposed;
 private readonly Dictionary<Type, Delegate> _applicationEventHandlers;
 public ApplicationEventDispatcher()
 {
 _applicationEventHandlers = new Dictionary<Type, Delegate>();
 }
 ~ApplicationEventDispatcher()
 {
 Dispose(false);
 }
 public void Dispose()
 {
 Dispose(true);
 GC.SuppressFinalize(this);
 }
 private void Dispose(bool disposing)
 {
 if (_disposed) return;
 if (disposing)
 {
 // free other managed objects that implement IDisposable only
 RemoveAllListeners();
 }
 // release any unmanaged objects
 // set the object references to null
 _disposed = true;
 }
 public void AddListener<T>(ApplicationEventHandlerDelegate<T> handler) where T : IApplicationEvent
 {
 if (_applicationEventHandlers.ContainsKey(typeof(T)))
 {
 Delegate handlersForType = _applicationEventHandlers[typeof(T)];
 _applicationEventHandlers[typeof(T)] = Delegate.Combine(handlersForType, handler);
 }
 else
 {
 _applicationEventHandlers[typeof(T)] = handler;
 }
 }
 public void RemoveListener<T>(ApplicationEventHandlerDelegate<T> handler) where T : IApplicationEvent
 {
 if (_applicationEventHandlers.ContainsKey(typeof(T)))
 {
 var handlerToRemove = Delegate.Remove(_applicationEventHandlers[typeof(T)], handler);
 if (handlerToRemove == null)
 {
 _applicationEventHandlers.Remove(typeof(T));
 }
 else
 {
 _applicationEventHandlers[typeof(T)] = handlerToRemove;
 }
 }
 }
 private void RemoveAllListeners()
 {
 foreach (Type handlerType in _applicationEventHandlers.Keys)
 {
 Delegate handlers = _applicationEventHandlers[handlerType];
 Delegate.RemoveAll(handlers, handlers);
 }
 }
 public void Dispatch(IApplicationEvent @event)
 {
 if (@event == null)
 {
 return;
 }
 if (_applicationEventHandlers.ContainsKey(@event.GetType()))
 {
 _applicationEventHandlers[@event.GetType()].DynamicInvoke(@event);
 }
 }
}
200_success
146k22 gold badges190 silver badges479 bronze badges
asked Jan 28, 2016 at 5:23
\$\endgroup\$
0

1 Answer 1

2
\$\begingroup\$

Delegate.RemoveAll has no effect on existing delegates. It actually constructs a new one. Delegates are immutable and cannot be changed after construction.

You can remove this line. I would not implement IDisposable or any cleanup code here at all. Just release reference on event dispatcher (it makes sense to do it anyway after calling Dispose().

answered Jan 28, 2016 at 5:48
\$\endgroup\$
2
  • \$\begingroup\$ Does this approach really not keep open any object references to the classes which have the handler methods, then? \$\endgroup\$ Commented Jan 28, 2016 at 7:48
  • \$\begingroup\$ As long as your event dispatcher is not referenced by variables in stack or pointed by static variables, directly or indirectly - references via delegates it keeps will not be counted by GC to prevent event handler objects from garbage collecting. Release your last reference to event dispatcher and you are good. \$\endgroup\$ Commented Jan 28, 2016 at 7:57

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.