System::EventHandler<T>

Combined delegate type and event subscriber list. Wraps std::function subscribers.

include/System/EventHandler.hpp

Status: Implemented

Overview

C# has separate concepts for the delegate type and the event keyword, which enforces encapsulation. sharp-runtime folds both into a single EventHandler<T> class that acts as both the delegate type and the subscriber list.

The template parameter T must derive from System::EventArgs.

Class Definition (abbreviated)

namespace System {
    template<typename T>
    class EventHandler {
    public:
        using HandlerType = std::function<void(Object*, T)>;

        void Add(HandlerType handler);
        void Remove(HandlerType handler);
        void Raise(Object* sender, T args);
        void Invoke(Object* sender, T args); // alias for Raise
        EventHandler<T>& operator+=(HandlerType handler);
        EventHandler<T>& operator-=(HandlerType handler); // needs verification
        int Size() const;
        bool Empty() const;
    private:
        std::vector<HandlerType> handlers_;
    };
}

Methods

Add()

void Add(HandlerType handler);

Appends a subscriber function to the internal list. Same as operator+=.

Remove()

void Remove(HandlerType handler);

Removes a previously added subscriber. Note: removing std::function objects requires matching by address or wrapping — see the note below.

Raise() / Invoke()

void Raise(Object* sender, T args);
void Invoke(Object* sender, T args);

Calls all registered subscribers in order with the given sender and args.

operator+=

EventHandler<T>& operator+=(HandlerType handler);

Adds a subscriber. Mirrors C# myEvent += handler; syntax.

Size() / Empty()

int Size() const;
bool Empty() const;

Returns the number of registered subscribers / whether the list is empty.

Usage Example

// EventArgs subclass
class ButtonClickArgs : public System::EventArgs {
public:
    int x, y;
    ButtonClickArgs(int x, int y) : x(x), y(y) {}
};

// Class with an event
class Button : public System::Object {
public:
    System::EventHandler<ButtonClickArgs> Click;
    GetTypeNameHPP();

    void press(int x, int y) {
        if (!Click.Empty()) {
            Click.Raise(this, ButtonClickArgs(x, y));
        }
    }
};

// Subscribing
Button btn;
btn.Click += [](System::Object* sender, ButtonClickArgs args) {
    std::cout << "Clicked at " << args.x << "," << args.y << "\n";
};

// Firing
btn.press(10, 20);

Comparison with C#

C# conceptsharp-runtime equivalent
delegate void Eh(object s, EventArgs e)EventHandler<T>::HandlerType (std::function)
event EventHandler<T> ClickEventHandler<T> Click (public field)
Click += handlerClick += handler (same)
Click -= handlerClick.Remove(handler) or Click -= handler
Click?.Invoke(this, args)if (!Click.Empty()) Click.Raise(this, args)
No C++ event keyword
C++ has no event keyword. sharp-runtime does not enforce that only the declaring class can Raise the event — all access is public on the EventHandler<T> object. For encapsulation, expose only the operator+= in the public interface if needed.
Removing std::function subscribers
std::function objects are not equality-comparable, which makes Remove tricky. A common pattern is to store the handler in a variable and remove by the same address, or use a wrapper with an ID. The exact mechanism in sharp-runtime's Remove implementation is: Needs verification

Related