How to actually create an event in C# - c#

I am a beginner in C# events , and delegates. Few questions that would make sense if you look at the URL I have used to learn about events.
Can I ever have an event without a delegate associated to it? The exmaples that I have found always have them together.
For example I do not understand how does the event get generated. I am totally lost, I understand that Tick is defined as an event but what is the Tick's event description? where do I define what constitutes the Tick?
Also where does the Tick value gets ever initailized. It seems that all the examples I have looked at never initialize the event and have a similar statement to statement : If (Tick ! =null) in the attached example but it is not obviuos where is the Tick is initialized. I have looked around and I just cant find any answer.
Thanks in advance for your help

No, events are just a special use of delegates. You can't have an event without a delegate (though you can have a delegate without an event - read up on delegates for more info).
Not really sure I understand your question here. The description of the event would be in the documentation. Looking at the code alone, you just know that there is an event called Tick on that object that you can attach an event handler to.
When you add an event handler to Tick (that's the += lines you see) it will become non-null. That's what those != null checks are doing - making sure that someone has attached onto the event.

An event is simply a combination of an add method and a remove method, both of which take a single parameter of the same delegate type. What the event does with a passed-in delegate is entirely up to the implementation.
The most common thing to do with an event delegate received in the Add handler is to Delegate.Combine it with the previously-added delegates (if any), but there are some other possibilities as well:
If an object will support many kinds of events, but many instances will have zero subscribers for most of them, one could add the delegate to a table. Many WinForms events do this.
If one wants to allow subscribers to use contravariant delegate types, one could place received delegates into an array, List<>, linked list, of delegates or delegate-holding objects.
If the event represents something that some types of objects would fire, but a particular instance never will, the event may simply discard the delegate. Consider, for example, an abstract ObservableFoo class with an abstract change-notification event, and a contract that says any time the instance's properties change it will invoke all passed-in delegates will be invoked; an ImmutableFoo class derived from it could accept subscription requests, but since it would never change, it would never have to invoke the passed-in delegates (or do anything else with them) and could simply discard them.
Since an event is a pair of methods which take a delegate type as a parameter, every event must "by definition" use delegates as its parameter type. All non-trivial events must store passed-in delegates in some form. The most common way to accept multiple subscriptions is to combine them into a multicast delegate (I dislike the design, btw, but it is the most common); other approaches may be employed, but an event which is going to use passed-in delegates must store them somehow.
BTW, there are two ways to declare an event in C#: one may supply the add/remove handlers explicitly, in which case the compiler will create a event with those handlers. One may also supply just the event name and delegate type, in which case the compiler will create an event with the specified name and scope, a private variable with the same name and appropriate delegate type, and thread-safe add/remove methods which add or remove the event from the indicated variable. Statements of the form eventName += something; or eventName -= something; will be processed as calls to the "add" or "remove" methods; all other uses of the name will refer to the delegate. Note that in old versions of C#, use of eventName += something; and eventName -= something; within a class would be processed using the += and -= operations on the delegate which were not thread-safe, but newer versions have changed that behavior.

Related

Is it safe to unsubscribe from an event that has never been subscribed?

For example, if these codes:
Button button1 = new Button();
// ...
button1.Click -= button1_Clicked;
are executed before:
button1.Click += button1_Clicked;
I found no error or exception, but I am wondering if there is any downside here.
If it is safe, why is it allowed to unsubscribe from an event that has never been subscribed?
I can't find a reference specific to events, but it is documented for the underlying function that events use, Delegate.Remove:
Returns source if value is null or if the invocation list of value is not found within the invocation list of source
So it will be safe at least for events that use implicit accessors.
Custom accessors are a whole other ball of wax, as one could implement the remove block however you want. I would assume people would mimic the implicit behavior, but this isn't enforced.

What is wrong with "delegate subtraction" if addition seems to be fine in C#? [duplicate]

When using myDelegate -= eventHandler ReSharper (version 6) issues:
Delegate subtraction has unpredictable result
The rational behind this is explained by JetBrains here. The explanation makes sense and, after reading it, I'm doubting all my uses of - on delegates.
How then,
can I write a non-auto event without making ReSharper grumpy?
or, is there a better and/or "correct" way to implement this?
or, can I just ignore ReSharper?
Here is simplified code:
public delegate void MyHandler (object sender);
MyHandler _myEvent;
public event MyHandler MyEvent
{
add
{
_myEvent += value;
DoSomethingElse();
}
remove
{
_myEvent -= value; // <-- ReSharper warning here
}
}
Don't be afraid! The first part of ReSharper's warning only applies to removing lists of delegates. In your code, you're always removing a single delegate. The second part talks about ordering of delegates after a duplicate delegate was removed. An event doesn't guarantee an order of execution for its subscribers, so it doesn't really affect you either.
Since the above mechanics can lead to unpredictable results, ReSharper issues a warning whenever it encounters a delegate subtraction operator.
ReSharper is issuing this warning because multicast delegate subtraction can have gotchas, it isn't condemning that language feature entirely. Luckily those gotchas are in fringe cases and you are unlikely to encounter them if you're just instrumenting simple events. There is no better way to implement your own add/remove handlers, you just gotta take notice.
I'd suggest downgrading ReSharper's warning level for that message to "Hint" so that you don't get desensitized to their warnings, which are usually useful.
You should not directly use delegates to sum or subtract. Instead your field
MyHandler _myEvent;
Should be instead declared as an event as well. This will solve the problem without risking your solution and still have the benefit of event usage.
event MyHandler _myEvent;
Usage of delegate sum or subtract is dangerous because you can lose events when simply assigning the delegate (as per declaration, the developer will not directly infer this is a Multicast delegate as when it is declared as an event). Just to exemplify, if the property mentioned on this question was not flagged as an event, the code below will case the two first assignments to be LOST, because someone simply assigned to the delegate (which is also valid!).
myObject.MyEvent += Method1;
myObject.MyEvent += Method2;
myObject.MyEvent = Method3;
When assigning Method3, I completely lost the two initial subscriptions. Event usage will avoid this problem and at same time remove the ReSharper warning.
set it to = null instead of using -=

Anonymous function delegate profit

I have a button event declared like this :
myButton.Click += new EventHandler(ButtonClicked);
private void ButtonClicked(Object s, EventArgs e)
{
this.Close();
}
I can do exactly the same like this :
myButton.Click += (s, e) => this.Close();
I'm sure the advantage of using the second way of doing it is not just aesthetic.
Why and when should I use the second method because now I'm confused? If it's just for the look of it, it doesn't look much cleaner when you have more than one instructions in the body of your anonymous function.
Technically there is no difference. Compiler will generate handler method in second case.
But frankly speaking I almost never use anonymous event handlers. Why? because they do not have names. IDE can't help me to find place where event is handled. Do you remember exact place where you subscribed with anonymous method? Well, you possibly remember that place. But I bet your teammates don't.
Also I don't like mixing styles of event handlers. Visual Studio generates for me button1_Click methods. I don't like having some handlers subscribed this way, and some subscribed in place.
And I like to see event argument type. And yes unsubscribing also matters sometime. And few more points - anonymous methods are useful for very simple logic (like closing form in your case), but them become very messy with something more complex. And I think that putting event handler in place breaks single responsibility of your method. It subscribes to event, does some other stuff, and handles event in same place. I like to separate things in order to make them more readable and maintainable.
The compiler generates a method for this anonymous function (s, e) => this.Close(); either way,
It's up to you where you want to use it, declaring it inside a method will however let you access variables declared in that method.
Well you have essentially implictly applied a delegate to your Click event.
You can't access this event in code anywhere else. The main advantage to this is that you can't call your method any where else in your class, by having a method you are inviting other "Team Members" to access the method in their code or potentially change the modifiers of it to what they think should happen.
Should you want to be able to override a method, then obviously inline anonymous assignments are a dis-advantage.
The usage is more or less dependant on how you want to handle access to the logic.
You can do it even more elegant if you do not need the arguments:
myButton.Click += delegate { this.Close(); };
but there is no profit besides elegant look behind it.
I prefer NOT to use lambda expressions ( => ) if I don't really need them as you can't change the scope code during debugging.
Anonymous Functions can be anonymous methods or lambda expressions. The lamba expression is of the form:
() => //dowork
Anonymous Methods are more verbose and support remains mainly for backwards compatibility. Anonymous Functions do not have a value or type in and of themselves, but it is convertible to a delegate or expression tree. Anonymous functions allow us to create in-line methods which are useful in cases such as setting up an event handler. This in-lining of methods allows developers to write code "in the same place". In other words, the handler is immediately available to the reader at the location where the event is handled.
I strive to in-line methods when the implementation is limited to a few statements and not re-useable (as is often the case in event handlers). Lamba Expressions can also used extensively in the framework's extensions methods Enumerable.Select, Where etc. And in place of Action or Func when using the new parallels library or calling Control.Invoke.
Here is a similiar subject: delegate keyword vs. lambda notation that considers anonymous delegates and lambda expressions. Particurarly, the answer there is: Once it is compiled, there is no difference between them.
The first method is easier to support, to make more complex and to reuse.
Also it is not obvious how to unsubscribe the second method from the event
As long as you don't need the parameters, you can even use:
myButton.Click += delegate { this.Close(); };
which looks even cleaner.
But by using anonymous delegates comes the cost of code reusability, as others have pointed out. Also in the article How to: Subscribe to and Unsubscribe from Events. Microsoft states that:
It is important to notice that you cannot easily unsubscribe from an
event if you used an anonymous function to subscribe to it. To
unsubscribe in this scenario, it is necessary to go back to the code
where you subscribe to the event, store the anonymous method in a
delegate variable, and then add the delegate to the event. In general,
we recommend that you do not use anonymous functions to subscribe to events if you will have to unsubscribe from the event at some later
point in your code.
One of the strong points of the anonymous methods, which also separates them from lambda expressions, is that:
... There is one case in which an anonymous method provides
functionality not found in lambda expressions. Anonymous methods
enable you to omit the parameter list. This means that an anonymous
method can be converted to delegates with a variety of signatures.
This is not possible with lambda expressions.
As a conclusion for the paragraph above we can say that you can either pass no parameters at all, or you should pass in the exact signature of the event handler:
myButton.Click += delegate(object sender, EventArgs e) { this.Close(); };

Am I missing something or is this not right way to declare event?

I came across this piece of code. It works, but is it not against the .net event declaration guidelines?
public event Action SessionTimeout;
While it is against standard C# practice, it is not an invalid event decleration.
The convention is that a .NET event uses a delegate that takes two parameters: the sender and the event arguments. However, this is an API convention, not a requirement. You may declare an event of any delegate type.
I would change it to:
public event Action SessionTimeout = delegate {};
So you don't have to check for null before raising it. I assume the potential extra CPU cycle this will cause won't affect your performance :)

Theoretical: Delegates passed to constructor

So I was wondering if something like this is possible:
I am a program, I am about to create an instance of one of my objects. I fire an event letting any subscribers know that I am about to create an object. As a part of this event I pass through a Hashtable that I will later pass to the constructor of my object.
Subscribers would then be able to modify this Hashtable yes? They could add entries for a delegate type with a delegate of that type as the value? Once the subscriber finishes doing their business, the pre-create event finishes. Would the changes made to the Hashtable be represented in the object that fired the event? So then if this Hashtable was passed to the constructor of an object, that object could potentially contain methods from an outside source?
So essentially -
Go to create object
Fire request delegate event
Use delegate hashtable modified by event in constructor of object
Object uses methods from hashtable in place of own if exists delegate of same type
Now object runs custom code on standard functions
Again, I really don't know if what I'm saying is even possible, or makes sense.
It's possible, but I would recommend against sending a HashSet<T> openly. The reason being that any subscriber could modify the values in the HashSet<T>.
Instead, I don't know that an event is the right course of action here. I would still use delegates, but I would not expose them as events. A pub/sub pattern might be better here (where an object that wants to be notified would pass the delegate through Sub/Unsub methods).
This allows you to modify the delegate signature so that the implementation will return the data values to you when you make the call (instead of passing around the HashSet<T>).
Then, instead of just making one call, you would call GetInvocationList to get each individual delegate. You would then loop through and collect the values that are returned.
From that point, you would aggregate the values appropriately and then pass that aggregate to the constructor of your objects.

Categories

Resources