using System.Collections.Generic;
event Action<T> ChangeValue;
event Action<object> ChangeObject;
event Action ChangeEmpty;
void InvokeChange(T value);
public static void Main()
IFoo<int> test1 = new Foo<int>();
test1.ChangeEmpty += () => Console.WriteLine("0) Empty!");
test1.ChangeObject += (o) => Console.WriteLine("1) Object: {0}", o);
test1.ChangeValue += (v) => Console.WriteLine("2) Value: {0}", v);
test1.ChangeObject += (o) => Console.WriteLine("3) Object: {0}", o);
test1.ChangeEmpty += () => Console.WriteLine("4) Empty!");
Console.WriteLine("\n--------\n");
IFoo<int> test2 = new Foo<int>();
test2.ChangeEmpty += EmptyHandler;
test2.ChangeObject += ObjectHandler;
Console.WriteLine("1) EMPTY, OBJECT");
test2.ChangeEmpty -= EmptyHandler;
test2.ChangeValue += ValueHandler;
Console.WriteLine("2) OBJECT, VALUE");
test2.ChangeObject -= ObjectHandler;
Console.WriteLine("3) VALUE ");
test2.ChangeObject += ObjectHandler;
test2.ChangeEmpty += EmptyHandler;
test2.ChangeValue += ValueHandler;
Console.WriteLine("4) VALUE, OBJECT, EMPTY, VALUE");
test2.ChangeValue -= ValueHandler;
test2.ChangeValue -= ValueHandler;
test2.ChangeEmpty -= EmptyHandler;
test2.ChangeObject -= ObjectHandler;
Console.WriteLine("5) <NONE>");
static void EmptyHandler() { Console.WriteLine(" - Empty!"); }
static void ObjectHandler(object val) { Console.WriteLine(" - Object: {0}", val); }
static void ValueHandler(int val) { Console.WriteLine(" - Value: {0}", val); }
public class Foo<T> : IFoo<T>
private EventHandlerProxy<T> changeProxy;
public event Action<T> ChangeValue = delegate {};
public event Action<object> ChangeObject
add => ChangeValue += changeProxy.Add(value);
remove => ChangeValue -= changeProxy.Remove(value);
public event Action ChangeEmpty
add => ChangeValue += changeProxy.Add(value);
remove => ChangeValue -= changeProxy.Remove(value);
public void InvokeChange(T value)
ChangeValue.Invoke(value);
public struct EventHandlerProxy<T>
private struct HandlerProxy
private Dictionary<object, HandlerProxy> handlerProxies;
public Action<T> Add(object handler)
if(handler.GetType() == typeof(Action<T>))
return (Action<T>)handler;
if (handlerProxies == null)
handlerProxies = new Dictionary<object, HandlerProxy>();
if (handlerProxies.TryGetValue(handler, out HandlerProxy handlerProxy))
handlerProxies[handler] = handlerProxy;
handlerProxy = new HandlerProxy() { count = 1 };
if (handler is Action<object>)
handlerProxy.proxy = (v) => ((Action<object>)handler).Invoke(v);
else if (handler is Action)
handlerProxy.proxy = (v) => ((Action)handler).Invoke();
handlerProxy.proxy = (v) => ((Action<T>)handler).Invoke(v);
handlerProxies.Add(handler, handlerProxy);
return handlerProxy.proxy;
public Action<T> Remove(object handler)
if (handler.GetType() == typeof(Action<T>))
return (Action<T>)handler;
if (handlerProxies == null)
handlerProxies = new Dictionary<object, HandlerProxy>();
if (handlerProxies.TryGetValue(handler, out entry))
handlerProxies.Remove(handler);
handlerProxies[handler] = entry;