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) { } }
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);
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.
|= just assigns the bitwise OR of a variable with another to the one on the LHS.
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 HasClickHandlers
to return whether there are any or not. That's not part of the core event model though.
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:
Flag approach : _getWarehouseForVendorCompletedSubscribed is a private variable initialized to false.
if (!_getWarehouseForVendorCompletedSubscribed) { _serviceClient.GetWarehouseForVendorCompleted += new EventHandler<GetWarehouseForVendorCompletedEventArgs>(_serviceClient_GetWarehouseForVendorCompleted); _getWarehouseForVendorCompletedSubscribed = true; }
Unsubscribe Approach :Include an unsubscribe everytime you want to subscribe.
_serviceClient.GetWarehouseForVendorCompleted -= new EventHandler<GetWarehouseForVendorCompletedEventArgs> (_serviceClient_GetWarehouseForVendorCompleted); _serviceClient.GetWarehouseForVendorCompleted += new EventHandler<GetWarehouseForVendorCompletedEventArgs> (_serviceClient_GetWarehouseForVendorCompleted);
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