开发者

C#: understanding event syntax

i need some help understanding how i can create a new custom event. i read from here ...

public delegate void ChangingHandler (object sender, CarArgs ca); 
public event ChangingHandler Change; 
...
private void car_Change(object sender, CarArgs ca) {
    MessageBox.Show(ca.Message());
} 
...
car.Change+=开发者_StackOverflownew Car.ChangingHandler(car_Change); // add event handler
...
Change(this,ca); // call event

1st, i dont really get the delegate part. in a normal variable declartion,

protected string str1;

but here i have the extra (ChangingHandler). how do i make sense of this? i know its something like a ChangingHandler will be used for handling the event but it throws me off abit.

public event ChangingHandler Change

then

car.Change+=new Car.ChangingHandler(car_Change)

i dont really get the syntax new Car.ChangingHandler(car_Change).


An event in C# is sort of like a collection of method pointers. It says "hey everyone, if you care about me, give me a pointer to a method I can invoke, I'll hold onto it, and when I feel like announcing to the world what is up, I'll invoke all the methods you gave me."

That way someone can give the event a pointer to their method, which is referred to as a "event handler". The event will call this method whenever the event's owner feels it is appropriate.

The delegate, in this sense, is nothing more than saying what kind of method the event will accept. You can't have one person giving the event a method that takes no arguments and one that takes 5, it'd have no idea how to call them. So the delegate is the contract between the event and the event handler, telling them both what to expect for the method signature.

In your case, it is probably better to just use EventHandler<T>, which is a built in delegate of the form void EventHandler<T>(object sender, T eventArgs) for your event delegate, like this:

public event EventHandler<CarArgs> Change;

C# doesn't actually have function pointers in the raw sense. Delegates handle this instead. They are like strongly typed, object oriented function pointers. When you call

car.Change+=new Car.ChangingHandler(car_Change);

You are giving the event a new delegate (function pointer) that points to your car_Change event handler, telling the event to call your car_Change method when it is ready. The delegate (new ChangeHandler(...) simply wraps the pointer to the car_Change method.


An event has a certain signature. This signature defines what a listener must look like in terms of what parameters and what return type it should have. This contract is expressed by defining a delegate. From your code sample:

public delegate void ChangingHandler (object sender, CarArgs ca);

Here we have defined a delegate for methods taking an object and a CarArgs as parameters, and with a void return type.

Next we declare the event as such:

public event ChangingHandler Change;

So, we have an event called Change, and listeners of the event must have the same signature as the ChangingHandler delegate.

Then we need a listener method:

private void car_Change(object sender, CarArgs ca) {
    MessageBox.Show(ca.Message());
} 

Here we can see how it has the same signature as the ChangingHandler delegate.

Finally we can attach the listner to the event:

car.Change+=new Car.ChangingHandler(car_Change)

So, we create a new ChangingHandler instance that refers to the car_Change method, and pass the delegate instance to the event.

All that said, I would recommend to use the predefined EventHandler<T> delegate instead of creating your own:

public event EventHandler<CarArgs> Change;


Also as it turns out you don't need the car.Change += new Car.ChangingHandler( car_Change ); sytax as it isn't very intuitive as you pointed out.

You could simply write car.Change += car_Change; assuming car_Change has the right method signature.


Events are based on the concept of delegates, a delegate is basically a method signature definition. That's all. Like in an interface how you define the method signatures, but you don't implement them, you do that in all of the classes that inherit that interface.

A delegate is a definition for a method signature, and for which you can define as many method body's are you like, for example, given this delegate (method signature definition):

public delegate void ChangingHandler (object sender, CarArgs ca);

You can define bodies with this delegate(method signature definition) as such:

public void SomeMethodWhichCreatesADelegateBody()
{
    ChangingHandler myChangingHandler = new ChangingHandler(
        delegate(object sender, EventArgs e) { /* the method body for myChangingHandler */ }
    );
}

This is an old style of defining a delegate though, now it's more readable to use lambdas instead of the delegate keyword to create the method body like I did, but that's not important to the issue.

Now events can be imagined of as a delegate (method signature definition) with an array of body's which are refered to as subscribing to the event, the syntax for subscribing a method body to an event is += and there's also syntax for removing a method body from an events subscription which is -=

So this code here defines an array of body's for the ChangingHandler delegate (method signature definition):

public event ChangingHandler Change;

And you can subscribe body's (add them to the array) to this grouping by calling in a method:

public void SomeMethodWhichSubscribesADelegateBodyToAnEvent()
{
    ChangingHandler myChangingHandler = new ChangingHandler(
        delegate(object sender, EventArgs e) { /* the method body for myChangingHandler */ }
    );

    Change += myChangingHandler;
}

Now the whole reason for the event to have an array of method bodys, which you get to define and add as you want, is so that whenever an event happens inside of the object who owns the event, that object can execute all of those methods to do whatever you want done when that event happens. The object which owns the object does so like this:

if (Change != null) // You wouldn't access an array without making sure it wasn't null, would you?
{
    Change(this, new CarArgs()); // This executes every method body in it's array using the signature definition the delegate defined.
    // The delegate simply exists so this code knows the method signature
    // so it can know how to call those method body's for you.
}


One crude way of thinking about it: the delegate type defines the "shape of function" that will be the basis of your event. So ChangingHandler is what the function must look like.

Going further, a delegate instance is like a function pointer. Think of it in those terms.

The public event ChangingHandler Change defines a function pointer called Change which will point to functions of shape ChangingHandler.

But currently, this function pointer is pointing at nothing. That's where the car.Change += new Car.ChangingHandler(car_Change) bit comes in.

Take this in two steps. Delegates are not normal function pointers; they are actually more like function pointer stacks, you can multiple functions to a delegate. This is why you hear people more commonly talk about "subscribing" to an event; adding your function to the event will mean it will be called when the event fires. You add your function to the delegate "stack" with the += operator.

You can't just add a function directly to a delegate, it has be expressed in terms of the delegate itself. This is done in a throwaway manner making a new object on the same line you add your function to the event; although since C# 2.0 I believe you can add functions directly without invoking the new syntax.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜