Events in D

kinke via Digitalmars-d digitalmars-d at puremagic.com
Tue Aug 29 13:27:11 PDT 2017


On Tuesday, 29 August 2017 at 05:10:25 UTC, bitwise wrote:
> I needed some C# style events, so I rolled my own. Long story 
> short, the result was unsatisfactory.
>
> [...]

> Anyways, I threw together some code while thinking about what 
> an event may look like in D:
>
> [...]

I like the C# event syntax too and came up with the following D 
analogon, just to prove that a primitive library-based solution 
in D is doable in 35 lines and can offer as much comfort as C# 
here.

struct Event(Args)
{
     alias CB = void delegate(Args);
     CB[] callbacks;

     void opOpAssign(string op)(CB handler)
         if (op == "+" || op == "-")
     {
         static if (op == "+")
             callbacks ~= handler;
         else
         {
             import std.algorithm.mutation : remove;
             callbacks = callbacks.remove!(x => x == handler);
         }
     }

     void opOpAssign(string op)(void function(Args) handler)
         if (op == "+" || op == "-")
     {
         import std.functional : toDelegate;
         opOpAssign!op(toDelegate(handler));
     }

     void opCall(Args args)
     {
         foreach (cb; callbacks)
             cb(args);
     }

     bool opCast(T)()
         if (is(T == bool))
     {
         return callbacks.length != 0;
     }
}

The following test code prints the expected output:

struct S
{
     int a;
     void handler(int arg)
     {
         printf("S.handler: this.a = %d, arg = %d\n", a, arg);
     }
}

void func(int arg) { printf("func: arg = %d\n", arg); }

void main()
{
     Event!int onChanged;
     auto s = S(666);

     assert(!onChanged);

     onChanged += (int arg) { printf("lambda: arg = %d\n", arg); };
     onChanged += &func;
     onChanged += &s.handler;
     assert(onChanged);
     onChanged(1);

     onChanged -= &s.handler;
     onChanged(2);

     onChanged -= &func;
     onChanged(3);
}


More information about the Digitalmars-d mailing list