Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C#, why can't I test if a event handler is null anywhere outside of the class that it's defined?

I am sure that I am just not understanding something fundamental about events and/or delegates in C#, but why can't I do the Boolean tests in this code sample:

public class UseSomeEventBase {     public delegate void SomeEventHandler(object sender, EventArgs e);     public event SomeEventHandler SomeEvent;     protected void OnSomeEvent(EventArgs e) {         // CANONICAL WAY TO TEST EVENT. OF COURSE, THIS WORKS.         if (SomeEvent != null) SomeEvent(this, e);     } }  public class UseSomeEvent : UseSomeEventBase {     public bool IsSomeEventHandlerNull() {         // "LEFT HAND SIDE" COMPILER ERROR         return SomeEvent == null;     } }  class Program {     static void Main(string[] args) {         var useSomeEvent = new UseSomeEvent();         useSomeEvent.SomeEvent +=new UseSomeEventBase.SomeEventHandler(FuncToHandle);         // "LEFT HAND SIDE" COMPILER ERROR         if (useSomeEvent.SomeEvent == null) {          }         var useSomeEventBase = new UseSomeEventBase();         useSomeEventBase.SomeEvent += new UseSomeEventBase.SomeEventHandler(FuncToHandle);         // "LEFT HAND SIDE" COMPILER ERROR         if (useSomeEventBase.SomeEvent == null) {          }     }      static void FuncToHandle(object sender, EventArgs e) { } } 
like image 1000
gabe Avatar asked Aug 07 '09 17:08

gabe


People also ask

What does '?' Mean in C?

Most likely the '?' is the ternary operator. Its grammar is: RESULT = (COND) ? ( STATEMEN IF TRUE) : (STATEMENT IF FALSE) It is a nice shorthand for the typical if-else statement: if (COND) { RESULT = (STATEMENT IF TRUE); } else { RESULT = (STATEMENT IF FALSE);

What is an operator in C?

C operators are one of the features in C which has symbols that can be used to perform mathematical, relational, bitwise, conditional, or logical manipulations. The C programming language has a lot of built-in operators to perform various tasks as per the need of the program.

What does |= mean in C++?

|= just assigns the bitwise OR of a variable with another to the one on the LHS.


2 Answers

An event is really just an "add" operation and a "remove" operation. You can't get the value, you can't set the value, you can't call it - you can just subscribe a handler for the event (add) or unsubscribe one (remove). This is fine - it's encapsulation, plain and simple. It's up to the publisher to implement add/remove appropriately, but unless the publisher chooses to make the details available, subscribers can't modify or access the implementation-specific parts.

Field-like events in C# (where you don't specify the add/remove bits) hide this - they create a variable of a delegate type and an event. The event's add/remove implementations just use the variable to keep track of the subscribers.

Inside the class you refer to the variable (so you can get the currently subscribed delegates, execute them etc) and outside the class you refer to the event itself (so only have add/remove abilities).

The alternative to field-like events is where you explicitly implement the add/remove yourself, e.g.

private EventHandler clickHandler; // Normal private field  public event EventHandler Click {     add     {         Console.WriteLine("New subscriber");         clickHandler += value;     }     remove     {         Console.WriteLine("Lost a subscriber");         clickHandler -= value;     } } 

See my article on events for more information.

Of course the event publisher can also make more information available - you could write a property like ClickHandlers to return the current multi-cast delegate, or HasClickHandlersto return whether there are any or not. That's not part of the core event model though.

like image 178
Jon Skeet Avatar answered Oct 14 '22 10:10

Jon Skeet


You can easily use a very simple approach here to not repeatedly subscribe to an event.

Either of the 2 approaches below can be used:

  1. Flag approach : _getWarehouseForVendorCompletedSubscribed is a private variable initialized to false.

        if (!_getWarehouseForVendorCompletedSubscribed)     {         _serviceClient.GetWarehouseForVendorCompleted += new EventHandler<GetWarehouseForVendorCompletedEventArgs>(_serviceClient_GetWarehouseForVendorCompleted);         _getWarehouseForVendorCompletedSubscribed = true;     } 
  2. Unsubscribe Approach :Include an unsubscribe everytime you want to subscribe.

    _serviceClient.GetWarehouseForVendorCompleted -= new      EventHandler<GetWarehouseForVendorCompletedEventArgs>    (_serviceClient_GetWarehouseForVendorCompleted);   _serviceClient.GetWarehouseForVendorCompleted += new         EventHandler<GetWarehouseForVendorCompletedEventArgs>        (_serviceClient_GetWarehouseForVendorCompleted); 
like image 42
Sunil Avatar answered Oct 14 '22 10:10

Sunil