Skip to content

Instantly share code, notes, and snippets.

@Deepscorn
Created July 19, 2018 23:43
Show Gist options
  • Select an option

  • Save Deepscorn/aac7f9c8657260f0dc517d0d0429f1d8 to your computer and use it in GitHub Desktop.

Select an option

Save Deepscorn/aac7f9c8657260f0dc517d0d0429f1d8 to your computer and use it in GitHub Desktop.
Some thoughts on how C# events can be made more friendly
using System;
namespace ConsoleApplication1
{
public delegate void SmartAction<T>(SmartAction<T> self, T data);
class EventSource<T>
{
private event SmartAction<T> actions;
public void AddListener(SmartAction<T> eventHandler)
{
actions += eventHandler;
}
public void RemoveListener(SmartAction<T> eventHandler)
{
actions -= eventHandler;
}
public void Fire(T eventData)
{
if (actions == null)
{
return;
}
Delegate[] delegates = actions.GetInvocationList();
for (int i = delegates.Length - 1; i >= 0; --i)
{
var action = (SmartAction<T>) delegates[i];
action(action, eventData);
}
}
}
internal class Program
{
public event SmartAction<int> ProgressChanged;
public static event Action EventA;
public static event Action EventB;
public static void Main(string[] args)
{
new Program().TestSequence();
}
public void TestSequence()
{
EventB += () => Console.WriteLine("b");
EventB();
SmartActionExt.Copy2(out EventB);
EventB();
}
public void TestFirst()
{
Action a = () => Console.WriteLine("a");
EventA += a.First();
EventA();
EventA();
EventA();
}
public void TestUntilEvent()
{
Action a = () => Console.WriteLine("a");
Action b = () => Console.WriteLine("b");
EventA += a.Until(ref EventB);
EventA();
EventA();
EventB();
EventA();
}
public void TestConcurentModification()
{
// no exception
Action b = () =>
{
Console.WriteLine("b");
};
Action a = () =>
{
Console.WriteLine("a");
b();
};
Action c = () =>
{
Console.WriteLine("c");
b();
};
a = (a + c).Until(ref b);
a();
b();
a();
}
public void TestUntil()
{
// result is b
Action b = () => Console.WriteLine("b");
Action a = () => Console.WriteLine("a");
a = a.Until(ref b);
a();
b();
a();
}
public void Test3()
{
EventA += () => Console.WriteLine("a");
Action b = () => Console.WriteLine("b");
Action c = () => Console.WriteLine("c");
EventA += (b + c);
EventA();
}
public void Test1()
{
var source = new EventSource<int>();
source.AddListener((self, n) =>
{
source.RemoveListener(self);
Console.WriteLine(n);
});
source.Fire(5);
source.Fire(25);
}
public void DoSome()
{
ProgressChanged += (self, progress) => { ProgressChanged -= self; };
}
}
public static class SmartActionExt
{
public static void DoNothing() {}
public static Action First(this Action a)
{
Action sub = null;
sub = () =>
{
sub = DoNothing;
a();
};
return () => sub();
}
// TODO CombineEventSource.FromSequence(ref eventA, ref eventB)
// pass to Until as second param. Via overload of Until (CombineEventSource must implement += operator)
public static Action Until(this Action a, ref Action b)
{
Action sub = () => a();
Action result = () => sub();
b += () =>
{
sub = DoNothing;
};
return result;
}
public static Action Copy(ref Action a)
{
return a;
}
public static void Copy2(out Action a)
{
a = null;
}
/* public static Action Sequence(ref Action event1, ref Action event2)
{
return a += b;
}*/
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment