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
| Method | Description |
|---|---|
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# pattern | sharp-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); |