Jabberwocky

Hi,

is there an MSDN help page that clearly lists the consequences of the "event" keyword in contrast to omitting it Also, the "event" keyword is not listed as an access modifier (like public, private), but in my understanding it is nothing else:
Code Block

public class MyTestClass
{
public event EventDelegate myEvent;
public EventDelegate myCallback;
...

A second class "MyApp" that makes an instance of MyTestClass, for example "myTest", can use both myEvent and myCallback to register its event handlers with +=. To my knowledge, the "event" keyword only restricts the access:
  • The only operations allowed on events are += and -=. So you can write myTest.myCallback = null, but you cannot write myTest.myEvent = null.
  • The return type of a += or -= operation on an event is void. With a normal delegate instance, the return value is the delegate instance itself.
Most documentation on C# events says a lot about how to use events, but does not explain these two simple differences. The best help page I found is chapter "10.7 Events" in the C# language specification. But is there an MSDN help page that clearly lists all differences between using the event keyword and simply omitting it

I've found a German page on this topic, which also does not state clearly what the differences are in detail: http://www.microsoft.com/germany/msdn/library/visualtools/FragenZuProgrammiersprachen.mspx mfr=true

Thank you.

Regards,
Stefan



Re: Visual C# Language Consequences of keyword "event" in C#

TaylorMichaelL

event is not an access modifier. It is a member definition. It identifiers a member as an event rather than as a property, field or method. It serves the same role as class in that it signifies the purpose of the name to follow. Without it the compiler might not be able to figure it out.

When you declare an event an internal field is created to back it. The field is set to a delegate type based upon the type of the event itself. By exposing an event you are inversing the calling order. Normally when somebody wants something from an object they call a method or retrieve a property value. With events the object can notify (or call back to) somebody else when something important happens like an operation completing or a property value changing. Refer to MSDN to learn all about events.

Events are used for completely different reasons than fields. You can not assign a value to an event. Rather you associate (through +=) a method with the event. When the event is raised (by the owning class) your method will be called. Again refer to MSDN for all the details on how events work. An important thing to remember about events is that multiple methods can be assigned to the same event.

Moving on to the delegate in your example. When you expose a delegate property/field you are effectively doing the same thing except there can be only one method that can be called. Events are arrays of delegates. See the difference Rarely, if ever, should you expose a delegate field/property directly. Prefer events as you never know when more than one handler should be called. About the only time you will use delegates directly is when you have a method that needs to call back to another method (such as when enumerating elements in an array) and when defining an event. In the case of a callback you would set one of the parameters to be a delegate type. This allows your method to call another method when it is done (or as it enumerates, or whatever). Refer to BeginInvoke for an example of this. You can also see Array.ForEach for an example.

So, in summary,

public event EventDelegate myEvent;

is an event where multiple methods can be associated with it. When the event is raised by the owning class all the methods in the list will be called. Methods are associated/removed from the event with += and -=.

public EventDelegate myCallback;

is a delegate field. You should almost never do this. If you do then at most one method may be associated with the callback. The callback still has to be invoked by your code. The more general solution is this:

public void EnumerateSomething ( object[] array, EnumerateCallback callback );

Note the naming convention. We use -Delegate when talking about events and their handlers. We use -Callback when talking about a single callback method.

Michael Taylor - 10/15/07

http://p3net.mvps.org





Re: Visual C# Language Consequences of keyword "event" in C#

eradicator

You can not assign a value to an event.

Except you can assign null, to effectively delete all the delegates.

EventDelegate delegate1 = new EventDelegate(MyMethod1);

EventDelegate delegate2 = new EventDelegate(MyMethod2);

thing.myEvent += delegate1;

thing.myEvent += delegate2;

// now the collection of delegates has 2 items in it

thing.myEvent = null;

// now it has none. This is effectively the same as removing each delegate individually:

thing.myEvent -= delegate1;

thing.myEvent -= delegate2;






Re: Visual C# Language Consequences of keyword "event" in C#

TaylorMichaelL

Technically you can also assign a delegate directly to the event (it wipes the original list and sets a new one). But that defeats the purpose of using an event to begin with. It also doesn't change the difference between using event and not using it when declaring a member. Delegate fields serve a different purpose than events. IMO.

MIchael Taylor - 10/15/07

http://p3net.mvps.org





Re: Visual C# Language Consequences of keyword "event" in C#

Peter Ritchie

I don't know where this information would be in MSDN; but the event keyword signals the compiler to generate different code than if you were just declaring a delegate. The difference between the two in what you can do is very small. You can add delegates to a delegate just as you can add event handlers (delegates) to an event. You can assign a delegate to a delegate and you can't assign a delegate to an event (only add and remove). And, of course, with a delegate, any code that has access to the delegate can invoke it--which isn't possible with an event.

In terms of what the compiler does with the two: with the event keyword the compiler generates an add_EventName and remove_EventName methods for the EventName event and declares the EventName event (IL understands events). The delegate is just a member with no special methods. When you perform instance.EventName += someDelegate, the compiler translates that into calls to add_EventName. When you perform instance.DelegateMember += someDelegate, the compiler actually generates inline code to combine someDelegate with the existing multicast delegate in DelegateMember. And, of course instance.DelegateMember = someDelegate, completely replaces any existing multicast delegate. When it comes to raising the event or calling the delegate, the syntax is the same.

In terms of C#, these differences are very subtle because the syntax is very similar. When you're producing code that will be used with other languages you start to notice the differences. With VB, for example, you wouldn't be able to use the existing event subscription/raise syntax with plain delegate members.






Re: Visual C# Language Consequences of keyword "event" in C#

Jabberwocky

Hi,

sorry, I do not understand what you mean. You say:

TaylorMichaelL wrote:

Moving on to the delegate in your example. When you expose a delegate property/field you are effectively doing the same thing except there can be only one method that can be called. Events are arrays of delegates. See the difference



Take an arbitrary code and remove any event-keyword, it will compile. So:
  1. It is not true that only one method may be called when exposing a delegate. One can add several methods to the field myCallBack in my example (in the same way as if it was an event).
  2. It is not true that events are arrays of delegates. Both events and delegates are a containers for methods in the same way.
I don't see your point that events are a different concept than delegates. Of course one write a lot about the idea of events in C#, but this is not my question. I am familiar with the MSDN Events tutorial.

Obivously, both members of my example have the type "EventDelegate", so they cannot be entirely different. Also you see from experimenting with code, you can do anything with the field without the "event" modifier that one can do with the field with the "event" modifier. Referring to the language specification chapter 10.7, the event modifier causes limited access, but I want a detailed list.

Regards,
Stefan





Re: Visual C# Language Consequences of keyword "event" in C#

TaylorMichaelL

No that is not correct. Many people try to make the association that delegates and events are the same but they aren't. This is common because most people learn about delegates when they study events the first time. Events use delegates to perform their magic but they are not the same. That is sort of like saying that because properties use methods they must be interchangeable with methods. That is not correct. Yeah you might be able to do it but they are not the same thing. If they were truly interchangeable then whatever you can do with an event you could do with a delegate and vice versa but that is not true.

When .NET was originally conceived delegates and events were far more distant. Events were truly arrays of delegates (backed by the multicast delegate class) while a delegate was a single method (backed by the Delegate) class. However before .NET was formally released it was realized that a single-cast delegate didn't really differ from a multi-cast delegate. Therefore a quick implementation change and a delegate field was a multicast delegate instead. Somebody on the CLR time wrote about this after v1.0 was released. You can search the INet for the article. I don't remember the name of it.

As a result though events and delegate (fields) are actually multicast delegates. Internally the class that implements this is an array of delegates. A delegate itself is a pointer to a single method with any extra baggage added. You can see the implementation by looking at Delegate. So yes events are arrays of delegates. However the delegate field you created also derives from multicast delegate and therefore is an array of delegates as well. When you hear the term delegate though you are generally talking about a single method or a method signature (depending upon usage) whereas when you are talking about an event you are (implicitly) referring to multiple delegates.

A delegate is a type pure and simple. It defines a function signature that allows one to call a method at runtime without having the actual method to invoke available at compile time. Delegates can be used standalone. They do not require events. Delegates can be passed to functions and can be returned from functions. A field/property can have a delegate type. An interface can contain a member of a delegate type.

Events are backed by a delegate field. An event can not be passed to/from a function, can not be assigned a value nor can it be a field in a class. All the assignments you do using += and -= are being redirected by the compiler to methods that work with the underlying delegate field and not the event itself. When you raise the event the compiler is again calling a hidden method that actually calls the underlying delegate field. An event is nothing more than a fancy (simplified) wrapper around the hidden delegate field. It is similar to how properties give you the illusion of field access when in reality you are (generally) calling methods.

An event has no impact on accessibility so I don't understand where you're coming up with that. Accessibility modifiers are completely separate concepts. Since an event is backed by a delegate you can technically remove the event keyword but now your event is no longer an event. It is simply a delegate field. While it might behave the same you've changed the semantics of the member. It is no longer an event as far as anybody is concerned. It won't show up as an event in designers nor will people treat it as such. They'll treat it like a public field. Static code analyzers will complain that you are exposing a public field which you should pretty much never do.

Michael Taylor - 10/15/07

http://p3net.mvps.org





Re: Visual C# Language Consequences of keyword "event" in C#

Peter Ritchie

Jabberwocky wrote:
Hi,

sorry, I do not understand what you mean. You say:

TaylorMichaelL wrote:

Moving on to the delegate in your example. When you expose a delegate property/field you are effectively doing the same thing except there can be only one method that can be called. Events are arrays of delegates. See the difference



Take an arbitrary code and remove any event-keyword, it will compile. So:
  1. It is not true that only one method may be called when exposing a delegate. One can add several methods to the field myCallBack in my example (in the same way as if it was an event).
  2. It is not true that events are arrays of delegates. Both events and delegates are a containers for methods in the same way.

I don't see your point that events are a different concept than delegates. Of course one write a lot about the idea of events in C#, but this is not my question. I am familiar with the MSDN Events tutorial.

Obivously, both members of my example have the type "EventDelegate", so they cannot be entirely different. Also you see from experimenting with code, you can do anything with the field without the "event" modifier that one can do with the field with the "event" modifier. Referring to the language specification chapter 10.7, the event modifier causes limited access, but I want a detailed list.

Regards,
Stefan

Events use multicast delegates, the event itself does not use an array of delegates. The event just invokes the one, multicast, delegate.

A delegate member can call 1 or more method, just like an event. You can use Delegate.Combine (which is what += on an event does) or use the same syntax as an event and use delegateMember += someDelegate. When you then invoke delegateMember you'll be invoking multiple methods.

You can do everything you can do with a delegate that you can with an event; but not vice versa (i.e. you can't assign a delegate to an event and you can't invoke an event from outside the class that it contains).






Re: Visual C# Language Consequences of keyword "event" in C#

Jabberwocky

TaylorMichaelL wrote:

No that is not correct. Many people try to make the association that delegates and events are the same but they aren't. This is common because most people learn about delegates when they study events the first time. Events use delegates to perform their magic but they are not the same. That is sort of like saying that because properties use methods they must be interchangeable with methods. That is not correct. Yeah you might be able to do it but they are not the same thing. If they were truly interchangeable then whatever you can do with an event you could do with a delegate and vice versa but that is not true.


I can only repeat: It is a fact that you can delete all "event" keywords in any piece of C# code and it will compile and run. So you can indeed exchange an event with a delegate. Why is this not correct Did you try it In addition, Peter Ritchie seems to confirm that:

Peter Ritchie wrote:

You can do everything you can do with a delegate that you can with an event; but not vice versa (i.e. you can't assign a delegate to a delegate member and you can't invoke an event from outside the class that it contains).

TaylorMichaelL wrote:

A delegate itself is a pointer to a single method with any extra baggage added. You can see the implementation by looking at Delegate. So yes events are arrays of delegates. However the delegate field you created also derives from multicast delegate and therefore is an array of delegates as well. When you hear the term delegate though you are generally talking about a single method or a method signature (depending upon usage) whereas when you are talking about an event you are (implicitly) referring to multiple delegates.


So I understand that we are talking about different things. When I talk about a delegate I mean the thing that arises when writing "delegate" in C#. But you refer to something else, that is the "Delegate" class and apparently a "delegate" is an array of "Delegate" instances and you call that a "multicast delegate". The internals and history of C# may be interesting, but of course I am not talking about the "Delegate" class but a "delegate" as declared with the C# keyword. A C# delegate is, like an event, an array of pointers to methods. So at least in this point, they are the same. Right


TaylorMichaelL wrote:

Events are backed by a delegate field. An event can not be passed to/from a function, can not be assigned a value nor can it be a field in a class. All the assignments you do using += and -= are being redirected by the compiler to methods that work with the underlying delegate field and not the event itself. When you raise the event the compiler is again calling a hidden method that actually calls the underlying delegate field. An event is nothing more than a fancy (simplified) wrapper around the hidden delegate field. It is similar to how properties give you the illusion of field access when in reality you are (generally) calling methods.



I don't see that it is of any relevance to the programmer, if the compiler treats events completely different than public delegate fields, because as a result, you can leave out the keyword "event" and have the same behaviour.

TaylorMichaelL wrote:

An event has no impact on accessibility so I don't understand where you're coming up with that. Accessibility modifiers are completely separate concepts. Since an event is backed by a delegate you can technically remove the event keyword but now your event is no longer an event. It is simply a delegate field. While it might behave the same you've changed the semantics of the member. It is no longer an event as far as anybody is concerned. It won't show up as an event in designers nor will people treat it as such. They'll treat it like a public field. Static code analyzers will complain that you are exposing a public field which you should pretty much never do.



Of course designers or static code analyzers can treat an event differently than a public delegate field. They can do that, because the source code differs. But I am talking about the C# language, not any side effects in other languages or analyzers. I also don't say that I will leave out any "event" keyword in the future, my colleagues would kill me. The keyword "event" seems to be an access modifier for me, as when deleting it, everything still compiles perfectly:
Code Block

public EventDelegate myEvent;


But when adding it, certain things are not allowed any more:
Code Block

public event EventDelegate myEvent;


These restriction are, to my knowledge:

  • The only operations allowed on events are += and -=. So you can write myTest.myCallback = null, but you cannot write myTest.myEvent = null.
  • The return type of a += or -= operation on an event is void. With a normal delegate instance, the return value is the delegate instance itself.
My original question was: Is this list complete Up to now, I have no answer. Regarding to Peter Ritchie, there is one additional thing:
  • You can't invoke an event from outside the class that it contains.
I don't understand the other point of Peter.

Peter Ritchie wrote:

you can't assign a delegate to a delegate member







Re: Visual C# Language Consequences of keyword "event" in C#

TaylorMichaelL

I don't understand if you're trying to justify your belief that it doesn't matter whether you specify event or not on a member then'll behave the same or whether you're truly trying to understand the differences. They are similar because they use the same underlying behavior but they are not the same. In geometric terms we could say they are congruent but not equal. If you want to leave off event and act they the field is an event go ahead. You are wrong but I don't have to deal with your code so I don't care. Yes they will behave the same but they are not equal. It is really no different than declaring a regular old field and then accessing it through a Get... and Set... method in lieu of using properties. If you want to be non-standard then go ahead.

As for delegate vs. the keyword. The delegate keyword is completely different than declaring a delegate field. The delegate keyword tells the compiler that you are defining a new type that derives from the multicast delegate. You can not, in C#, derive from the multicast delegate class directly (even though it is just a regular old class). It is just like the fact that you have to use enum to declare enumerations rather than deriving from Enum itself. Same with structures. The Delegate class is how you internally represent all delegate types when you don't know the type in advance (think of it like object exept it only works with delegates). If you use reflector or equivalent to look at the actual type declaration that was created you'll see it is just another class that derives from the multi-cast delegate (and hences becomes an array of delegates). Multicast delegate itself derives from Delegate.

When you declare a field of a delegate type it is no different then declaring a field of type int, string or whatever. Internally you'll see the field has the underlying type that was created for the delegate when it was originally defined. As for whether it matters, again it is semantics. The same philosophy can be applied to properties and enums as well. It's non-standard. If you want to do it then go ahead. Your code will be less useful to others in my opinion but it's your call.

No event is not an access modifier. You can use = with an event just like you can a delegate. Operator return types are a little different. The +=, -=, *= and any other = operators have no return type (whether it is an event or not is irrelevant). x += y maps to x = x + y. If it did then you could chain operators but it doesn't. x += y += z is illegal syntax. For events the designers chose to use the += syntax because it was familiar to developers not because it conveys any special meaning about return types or operators being used. They could just as easily have used => or ::= or +=+ and it wouldn't have mattered. Unless you're talking about certain operators or functions return type has no meaning.

I've shared all I really can about this topic. I'm detaching myself from this discussion as I don't think I can provide any more insight or make myself any more clear. Perhaps you'll get the answers you're looking for from someone else. Good luck.

Michael Taylor - 10/15/07

http://p3net.mvps.org





Re: Visual C# Language Consequences of keyword "event" in C#

Peter Ritchie

Jabberwocky wrote:
I don't understand the other point of Peter.

Peter Ritchie wrote:

you can't assign a delegate to a delegate member



sorry, that should have been "you can't assign a delegate to an event" not "you can't assign a delegate to a delegate member".




Re: Visual C# Language Consequences of keyword "event" in C#

Peter Ritchie

TaylorMichaelL wrote:

You can use = with an event just like you can a delegate.

From outside of the class that declares the event, you cannot use the = operator on an event. You can from within the class that declares the event. For example:

class One

{

public event EventHandler MyEvent;

public One()

{

MyEvent = null; // no error

}

}

One one = new One();

one.MyEvent = null; // error CS0070






Re: Visual C# Language Consequences of keyword "event" in C#

Nimrand

Also, you could call a the method pointed to by a delegate property from outside the class, but this is not allowed with an event. In other words "one.MyEvent(this, new EventArgs())" is not valid outside the One class.

What an event declaration actually exposes to the outside world is an add and remove operation. You can define these operations manually as follows:

Code Block

public event EventHandler MyEvent {

add {

...

}

remove {

...

}

}

In this case, you have to create your own backing field. However, in most cases you use the abbreviated syntax that omits the add/remove blocks. In this case, the compiler creates a backing field for you. When you use the event's identifier from within the class, you are actually referring to the backing field, not the event. Outside the class, the event's identifier refers to the event, which only allows you to add and remove delegates (via the auto-generated operations that add and remove delegates from the backing field). This duel-use of the event's identifier may be part of the cause of your confusion.





Re: Visual C# Language Consequences of keyword "event" in C#

Peter Ritchie

Among other things, declaring an event makes the underlying delegate an implementation detail and the modification of that delegate is forced to be done through the add/remove interface created by the compiler. It's a form of abstraction, and as Nimrand points out, you can override that interface and use whatever implementation detail you need (e.g. not a delegate within the containing class).