Delegates & Events

Action, Func, Predicate, EventHandler, AsyncCallback, and delegate patterns.

Delegate Types

C# delegates map to std::function type aliases.

Action (no return value)

include/System/Action.hpp

namespace System {
    using Action = std::function<void()>;           // C# Action
    template<typename T>
    using ActionT = std::function<void(T)>;          // C# Action<T>
    template<typename T1, typename T2>
    using ActionT2 = std::function<void(T1,T2)>;    // C# Action<T1,T2>
    template<typename T1, typename T2, typename T3>
    using ActionT3 = std::function<void(T1,T2,T3)>; // C# Action<T1,T2,T3>
}

Func (with return value)

include/System/Func.hpp

namespace System {
    template<typename R>
    using Func = std::function<R()>;                 // C# Func<TResult>
    template<typename T, typename R>
    using FuncT = std::function<R(T)>;              // C# Func<T,TResult>
    template<typename T1, typename T2, typename R>
    using FuncT2 = std::function<R(T1,T2)>;         // C# Func<T1,T2,TResult>
    template<typename T1, typename T2, typename T3, typename R>
    using FuncT3 = std::function<R(T1,T2,T3)>;      // C# Func<T1,T2,T3,TResult>
}

Predicate

include/System/Predicate.hpp

namespace System {
    template<typename T>
    using Predicate = std::function<bool(T)>;  // C# Predicate<T>
}

AsyncCallback

include/System/AsyncCallback.hpp

Compatibility alias for asynchronous callback patterns.

EventArgs

include/System/EventArgs.hpp | src/System/EventArgs.cpp

Base class for event argument types. Used with EventHandler<T>.

class EventArgs {
public:
    static const EventArgs Empty;
};

EventHandler<TEventArgs>

include/System/EventHandler.hpp

EventHandler<T> is the most important class in the delegate/event system. It combines both the callback type signature and the subscriber list — because C++ has no event keyword.

ℹ Design decision
In .NET, EventHandler<T> is only a delegate type (callback signature). The event keyword stores subscribers. In sharp-runtime, EventHandler<T> combines both because C++ has no equivalent of event. This is intentional to keep ported code visually close to the original C# source.

Handler Type

// One subscribed callback:
using HandlerType = std::function<void(Object* sender, const TEventArgs& e)>;

Key Methods

MethodDescription
operator+=(HandlerType)Subscribe (mirrors C# += syntax). Token is discarded.
Token Add(HandlerType)Subscribe and get a removal token.
Remove(Token)Unsubscribe by token. No-op if not found.
Clear()Remove all subscribers.
Raise(Object*, TEventArgs)Fire event — calls all subscribers in order.
Invoke(Object*, TEventArgs)Alias for Raise().
Empty()True if no subscribers.
Size()Number of subscribers.

Usage Example

// Define event arguments
struct KeyPressedEventArgs : public System::EventArgs {
    char key;
};

// Declare an event field (in a class)
class Keyboard {
public:
    System::EventHandler<KeyPressedEventArgs> KeyPressed;

    void SimulateKeyPress(char k) {
        KeyPressedEventArgs args;
        args.key = k;
        KeyPressed.Raise(this, args);
    }
};

// Subscribe and fire
Keyboard kb;
kb.KeyPressed += [](System::Object* sender, const KeyPressedEventArgs& e) {
    std::cout << "Key: " << e.key << "\n";
};
kb.SimulateKeyPress('A');  // prints "Key: A"

Removing a Specific Subscriber

auto token = event.Add([](System::Object* s, const EventArgs& e) {
    // handler code
});
// ... later:
event.Remove(token);

Comparison with C#

C# patternsharp-runtime C++ equivalent
event EventHandler<T> Evt;System::EventHandler<T> Evt;
Evt += handler;Evt += handler;
Evt -= handler;auto tok = Evt.Add(handler); ... Evt.Remove(tok);
Evt?.Invoke(sender, args);if (!Evt.Empty()) Evt.Raise(sender, args);