using System;

public class Test { public int num = 44; }

public class Signal
{
  private int _listenerCount;

  public object Arg1;
  public object Arg2;
  public object Arg3;
  public event Action All;
  public event Action<Signal> On;
  
  // niladic, monadic, dyadic, triadic, and never greater
  public void Do(object arg1 = null, object arg2 = null, object arg3 = null)
  {
    if(On != null)
    {
      // Escape
      if(_listenerCount > 0)
        throw new System.ArgumentException("All handlers must properly Use() before Do() may be reused.");
      
      // Args
      Arg1 = arg1;
      Arg2 = arg2;
      Arg3 = arg3;
      
      // Update
      _listenerCount = On.GetInvocationList().Length;

      // Notify
      On(this);
    }
  }
  
  public void Use()
  {
    // Escape
    if(_listenerCount == 0)
      return;
    
    // Update
    _listenerCount--;
    
    // All
    if(_listenerCount == 0)
      if(All != null)
        All();
  } 
}

public class Signals
{
  public static Signal ChangeLevel = new Signal();
}

public class Program
{ 
  public static void Main()
  {
    Signals.ChangeLevel.On += OnTest1;
    Signals.ChangeLevel.On += OnTest2;
    Signals.ChangeLevel.All += OnAll;
    Signals.ChangeLevel.Do(40, "test", new Test());
  }
  
  public static void OnTest1(Signal signal)
  {
    Console.WriteLine("Test1 " + signal.Arg3);
    signal.Use();
  }
  
  public static void OnTest2(Signal signal)
  {
    Console.WriteLine("Test2 " + signal.Arg1);
    signal.Use();
  }
  
  public static void OnAll()
  {
    Console.WriteLine("All!!");
  }
}