In C# I can check if an event has any listeners:
C# Example:
public static event EventHandler OnClick;
if (OnClick != null)
OnClick(null, new EventArgs() );
In C++/CLI checking if the event is null is not necessary.
C++/CLI Example:
delegate void ClickDelegate( Object^ sender, MyEventArgs^ e );
event ClickDelegate^ OnClick;
OnClick (sender, args);
BUT, in the project I am working on, I don’t want to construct the MyEventArgs object if there are no listeners.
How do I find out if OnClick has any listeners in C++?
Based on the comment discussion with @BenVoigt on @svick's original answer and the new MSDN article on C++/CLI events, I have created a minimal example of how to do this correctly. This code compiles and runs in a Visual Studio 2013 CLR project template targeting .NET 4.5. I haven't tested on other runtimes and targets, but it only uses basic .NET components.
Make the backing field private
Lock each add, remove, and raise call with System::Threading::Monitor
Use the standard event handler convention:
void MyEventHandler(Object ^sender, MyEventArgs ^e);
Use +=
and -=
except when the backing field is a nullptr
// compile with: /clr
#include "stdafx.h"
using namespace System;
using System::Threading::Monitor;
public delegate void MyDelegate(Object ^sender, EventArgs ^e);
ref class EventSource {
private:
MyDelegate ^myEvent;
Object ^eventLock;
public:
EventSource()
{
eventLock = gcnew Object();
}
event MyDelegate^ Event {
void add(MyDelegate^ handler) {
Monitor::Enter(eventLock);
if (myEvent == nullptr)
{
myEvent = static_cast<MyDelegate^> (
Delegate::Combine(myEvent, handler));
}
else
{
myEvent += handler;
}
Monitor::Exit(eventLock);
}
void remove(MyDelegate^ handler) {
Monitor::Enter(eventLock);
if (myEvent != nullptr)
{
myEvent -= handler;
}
Monitor::Exit(eventLock);
}
void raise(Object ^sender, EventArgs ^e) {
Monitor::Enter(eventLock);
if (myEvent != nullptr)
myEvent->Invoke(sender, e);
Monitor::Exit(eventLock);
}
}
void Raise()
{
Event(this, EventArgs::Empty);
}
};
public ref struct EventReceiver {
void Handler(Object ^sender, EventArgs ^e) {
Console::WriteLine("In event handler");
}
};
int main() {
EventSource ^source = gcnew EventSource;
EventReceiver ^receiver = gcnew EventReceiver;
// hook event handler
source->Event += gcnew MyDelegate(receiver, &EventReceiver::Handler);
// raise event
source->Raise();
// unhook event handler
source->Event -= gcnew MyDelegate(receiver, &EventReceiver::Handler);
// raise event, but no handlers
source->Raise();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With