Event being declared as Delegate [duplicate] - c#

This question already has answers here:
Event declaration with assignment to empty delegate
(2 answers)
Closed 4 years ago.
While going through C# example codes, I have found this declaration:
public event myEventHandler myEvent = delegate { };
What does this statement mean? It is not inline with other declarations of delegate I have seen on internet.

public event myEventHandler myEvent = delegate { };
Assigns an function to the event when an instance of the class is created by simply delegating it with anonymous function.
When assigning a function to event's invocation list, the following notation is used
myClass.myEvent += delegate { };
However the following assignment is also valid inside the parent class, but it basically discards all the existing invocation list unless it is used in ctor.
myEvent = delegate {};

Related

Attach an event handler to an event stored in a list

I want to make a list that stores some events and attach event handler to the event through the list.
So I make a List<dele> add the event anEvent into it, then I try to attach an event handler to that event, but at last anEvent still got no event handler attached to it, the program outputs True. But the delegate stored at list[0] did get the lambda expression.
public delegate void dele();
class Program
{
static event dele anEvent;
static void Main(string[] args)
{
List<dele> list=new List<dele>();
list.Add(anEvent);
list[0]+=()=>{Console.WriteLine("BEEP!");};
Console.WriteLine(anEvent==null);
}
}
Isn't delegate a reference type? It seems that eventhandler and list[0] refers to different objects. I wonder why.
If I want that anEvent gets the event handler when I attach the handler to list[0], what should I do?
Thanks!
A delegate is basically a contract for a method implementation.
Kinda like an interface is a contract for class implementations.
The CLI (Common Language Infrastructure) specification says that delegates are reference types.
A delegate is a reference type that can be used to encapsulate a named
or an anonymous method. Delegates are similar to function pointers in
C++; however, delegates are type-safe and secure. For applications of
delegates, see Delegates and Generic Delegates.
Have a look at this question and also have a look at that one.
I have converted the method into a non anonymous method for debugging reasons
public delegate void dele();
public static event dele anEvent;
static void Main(string[] args) {
List<dele> list = new List<dele>();
list.Add(anEvent);
list[0] += Dele;
list[0].Invoke(); //this actually gets invoked and does not throw!
anEvent = list[0];
Console.WriteLine(anEvent == null); //the output is false
anEvent.Invoke(); // this also gets s invoked and does not throw
}
private static void Dele() { //this gets invoked 2 times as expected
Console.WriteLine("Beep"); // this gets printed after invoking the event
}

What is the difference between these two event declarations? [duplicate]

This question already has answers here:
What are the differences between delegates and events?
(11 answers)
Closed 6 years ago.
I have two events in a class
public event AcquiredDataEvent OnNewAcquiredData;
public delegate void AcquiredDataEvent(int[] newData);
public ScanStartedEvent ScanStarted;
public delegate void ScanStartedEvent();
I just realized that ScanStarted does not have the keyword event before it. Most likely the result of a typo by me, though it still works as expected.
What is the difference between the two events if any?
ScanStarted is not event. It's just a field of delegate type.
It can be invoked outside of class where field is declated.
It does not provide add/remove methods (that is what event is, like property is a pair of get/set methods) for attaching/removing event handlers - you can simply assign new delegate to ScanStarted field.
BTW Just like you can have property without backing field
public int Value
{
get { return 42; }
set { Console.WriteLine($"Haha, keep {value} for yourself"); }
}
You can have event without delegate field under the hood
public event AcquiredDataEvent OnNewAcquiredData
{
add { Console.WriteLine("Trying to attach some handlers?"); }
remove { Console.WriteLine("Haha, you should attach something first!"); }
}

Subscribing to events with = instead of +=

Is there anything wrong with subscribing to event with
MyPopup.CustomPopupPlacementCallback = popupFixCentered;
instead of:
MyPopup.CustomPopupPlacementCallback += popupFixCentered;
For example, if I am changing to different callback from another method I want to make sure I have only one callback subscribed without needing to -= the correct one.
Well, it sounds like you didn't try it. If you did, you would get the following compilation error:
The event 'XXX' can only appear on the left hand side of += or -= (except when used from within the type 'YourClass')
The error is pretty clear: you can only use the += and -= operators on the event.
If you try to assign to the event from within the class that defines the event, then it will "work". But the reason it appears to be able to assign to an event in that case is because it's actually not accessing the event. It's accessing an auto-generated private delegate instance that you may not realize is actually there.
Quoting from Chris Burrows' article on the subject:
outside of the class or struct that defines a field-like event E, binding to the name E resolves to the event itself, on which the only legal operation is calling an accessor; inside the class or struct that defines a field-like event E, binding to the name E resolves to the private delegate field.
To understand this, you need to visualize that when you define an event such as:
public event EventHandler MyEvent;
... what you don't see, is that it actually gets translated into something like this (I'm copying this from Jon Skeet's article on events and delegates. Also note that the exact code it gets translated into has changed between versions of C#, so it may be a bit different, but the general idea is the same):
private EventHandler _myEvent;
public event EventHandler MyEvent
{
add
{
lock (this)
{
_myEvent += value;
}
}
remove
{
lock (this)
{
_myEvent -= value;
}
}
}
So when you access MyEvent from outside the class, you can only invoke the add and remove methods through the += and -= operators.
But from within the class, accessing MyEvent means something different. It actually becomes a reference to that private _myEvent delegate variable that you can't see, but it is there. Because this is a delegate type, then you can use the assignment (=) operator on it.
So, to achieve what you want, you could define a public method in the same class that defines the event, and use that method to set your new event handler.
Something like this:
public class MyClass
{
public event EventHandler MyEvent;
public void setSingleEventHandler(EventHandler eventHandler)
{
this.MyEvent = eventHandler;
}
}
But if you are going to do that, then it defeats the purpose of the event type. If you only want to invoke a single event handler at most at any given time, then defining it this way (without using the event keyword) makes more sense:
public class MyClass
{
public EventHandler MyEvent { get; set; }
}
References
Jon Skeet article: Delegates and Events
Chris Burrows article: (also check out the rest of the series): Events get a little overhaul in C# 4, Part II: Semantic Changes and +=/-=
I just tested it. Yes, you can use the = operator to assign to an event. (Edit: Apparently only from within the same class)
delegate void Foo();
event Foo bar;
Method()
{
bar = () => { Console.WriteLine("1"); };
bar();
bar = () => { Console.WriteLine("2"); };
bar();
}
Produces the output:
1
2
But if you try to assign from outside the class, it will give you an error.
You can get around this by using a java-style set method:
SetBar(Foo foo)
{
bar = foo;
}
Only time I'd ever recommend java convention for external access of properties :)

Why is a C# EventHandler Equal to an Event in MSN example?

The following is an example from MSN website. This is a good example, I just do not understand what this line:
EventHandler<CustomEventArgs> handler = RaiseCustomEvent;
is doing?
Is not RaiseCustomEvent an event based on the definition at the top of the program?
Why is an Event is equated to an EventHandler? These are two different types.
Where is RaiseCustomEvent being initialized? If it is not initialized how can we copy it or why do we want to copy something uninitialized to something else?
What is the handler variable there for? Is that an event or an event handler?
I'm very confused and am trying hard to get this event/event handler/delegate issue understood.
Here is the sample code from MSN
namespace DotNetEvents
{
using System;
using System.Collections.Generic;
// Define a class to hold custom event info
public class CustomEventArgs : EventArgs
{
public CustomEventArgs(string s)
{
message = s;
}
private string message;
public string Message
{
get { return message; }
set { message = value; }
}
}
// Class that publishes an event
class Publisher
{
// Declare the event using EventHandler<T>
public event EventHandler<CustomEventArgs> RaiseCustomEvent;
public void DoSomething()
{
// Write some code that does something useful here
// then raise the event. You can also raise an event
// before you execute a block of code.
OnRaiseCustomEvent(new CustomEventArgs("Did something"));
}
// Wrap event invocations inside a protected virtual method
// to allow derived classes to override the event invocation behavior
protected virtual void OnRaiseCustomEvent(CustomEventArgs e)
{
// Make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes
// immediately after the null check and before the event is raised.
EventHandler<CustomEventArgs> handler = RaiseCustomEvent;
// Event will be null if there are no subscribers
if (handler != null)
{
// Format the string to send inside the CustomEventArgs parameter
e.Message += String.Format(" at {0}", DateTime.Now.ToString());
// Use the () operator to raise the event.
handler(this, e);
}
}
}
//Class that subscribes to an event
class Subscriber
{
private string id;
public Subscriber(string ID, Publisher pub)
{
id = ID;
// Subscribe to the event using C# 2.0 syntax
pub.RaiseCustomEvent += HandleCustomEvent;
}
// Define what actions to take when the event is raised.
void HandleCustomEvent(object sender, CustomEventArgs e)
{
Console.WriteLine(id + " received this message: {0}", e.Message);
}
}
class Program
{
static void Main(string[] args)
{
Publisher pub = new Publisher();
Subscriber sub1 = new Subscriber("sub1", pub);
Subscriber sub2 = new Subscriber("sub2", pub);
// Call the method that raises the event.
pub.DoSomething();
// Keep the console window open
Console.WriteLine("Press Enter to close this window.");
Console.ReadLine();
}
}
}
An event is to a delegate type what a property is to any other type.
If you have a property such as this:
public string Name {get;set;}
Obviously you can do something like this:
string name = Name;
The property has an underlying string value that is accessed/modified by the property.
Similarly, an event has a delegate under the hood, and that delegate is of the type defined in the event declaration. That it's an event simply defines how handlers of that event are added/removed from that underlying delegate.
From within the declaring type (that's a key point; you can't do this externally) you can access that underlying delegate in order to invoke it. That's the reason for doing the code that you see; they're accessing the underlying delegate so that they can verify that it has some handlers within it, and if so, it invokes them.
So, to answer the questions explicitly:
Is not RaiseCustomEvent an event based on the definition at the top of the program?
RaiseCustomEvent is the type of the underlying delegate that the event wraps.
Why is an Event is equated to an EventHandler? These are two different types.
It's not strictly equality. It's pulling out the underlying delegate from within the event.
Where is RaiseCustomEvent being initialized? If it is not initialized how can we copy it or why do we want to copy something uninitialized to something else?
In this case it's using the automatic add/remove implementations that the framework will provide, rather than manually defining them. The automatically defined add handler will initialize the underlying delegate if it is currently null. If the event declaration would
define a custom add handler, it would need to handle that case.
What is the handler variable there for? Is that an event or an event handler?
It is a single delegate that represents the combination of all of the event handlers. Within it's definition will be an invocation list of all of the individual methods that make up that delegate. So it's not a single event handler, it's the collection of all of them. Since it's pulled out of the event it no longer strictly represents that event; it's a copy of what was in the event at some point in the past. You cannot change the event (i.e. add a new handler) using the delegate that you've pulled out of it.
I'll try the four questions you pose:
1) Is not RaiseCustomEvent an event based on the definition at the top of the program ?
The CustomEventArgs class holds some data (arguments) for the event we want to declare. It is used as type parameter in the type EventHandler<CustomEventArgs>. This last type is a delegate type, which means it represents one or more methods of the same signature and return type. (Zero methods will be a null reference as the value of the delegate.)
The type of the event RaiseCustomEvent is that delegate type, EventHandler<CustomEventArgs>.
2) Why an Event is equated to an EventHandler? These are two diffeent types
An event consists on a pair of special methods, accessors, one add accessor and one remove accessor. Both have one parameter of the same type which is called the type of the event. That type must be a delegate type. In this case that type is EventHandler<CustomEventArgs>.
In this example the event is a so-called field-like event. It generates a backing field of the same type, EventHandler<CustomEventArgs>, the delegate type. That field has the same name as the event itself!
When they do:
// Make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes
// immediately after the null check and before the event is raised.
EventHandler<CustomEventArgs> handler = RaiseCustomEvent;
they copy the current value of that backing field into the local variable handler. The comment describes why. They want to check for null before they invoke the delegate.
3) Where is RaiseCustomEvent have been initialized? If not initialized how can we copy or why do we want to copy something uninitialized to soemthig else.
It usually gets initialized when people use the add accessor of the event. This takes place through the special C# syntax +=. This is called subscribing to the event. See the Subscriber class.
Actually pub.RaiseCustomEvent += HandleCustomEvent; translates to pub.add_RaiseCustomEvent(HandleCustomEvent);, so it is a call to the add accessor. The add accessor is generated by the compiler (in a field-like event), and it initializes the backing field.
4)I do not know what is handler variable? is that an event or an event handler ?
It is a delegate. It is not an event. It is a copy of the backing field of the field-like event at one moment in time.

I would like to create an event handler [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Create event handler for OnScroll for web browser control
I would like to create an event handler for a web browser control scrolling.
webCompareSQL.Document.Window.Scroll
Can some one show me how to create an event handler?
In the class you add a delegate and an event, and usually a simple internal method that checks for null and calls the event:
public delegate void ScrollHandler();
public event ScrollHandler Scrolled;
internal void OnScrolled()
{
if (this.Scrolled != null)
this.Scrolled();
}
Then in the actual code you would register a method for the event using:
MyClass.Scrolled += new ScrollHandler(MyMethod);
void MyMethod()
{
Console.WriteLine("It was scrolled.");
}

Categories