What are the differences between delegates and an events? Don't both hold references to functions that can be executed?
相关问题
- Sorting 3 numbers without branching [closed]
- Graphics.DrawImage() - Throws out of memory except
- Why am I getting UnauthorizedAccessException on th
- 求获取指定qq 资料的方法
- How to know full paths to DLL's from .csproj f
An event in .net is a designated combination of an Add method and a Remove method, both of which expect some particular type of delegate. Both C# and vb.net can auto-generate code for the add and remove methods which will define a delegate to hold the event subscriptions, and add/remove the passed in delegagte to/from that subscription delegate. VB.net will also auto-generate code (with the RaiseEvent statement) to invoke the subscription list if and only if it is non-empty; for some reason, C# doesn't generate the latter.
Note that while it is common to manage event subscriptions using a multicast delegate, that is not the only means of doing so. From a public perspective, a would-be event subscriber needs to know how to let an object know it wants to receive events, but it does not need to know what mechanism the publisher will use to raise the events. Note also that while whoever defined the event data structure in .net apparently thought there should be a public means of raising them, neither C# nor vb.net makes use of that feature.
What a great misunderstanding between events and delegates!!! A delegate specifies a TYPE (such as a
class
, or aninterface
does), whereas an event is just a kind of MEMBER (such as fields, properties, etc). And, just like any other kind of member an event also has a type. Yet, in the case of an event, the type of the event must be specified by a delegate. For instance, you CANNOT declare an event of a type defined by an interface.Concluding, we can make the following Observation: the type of an event MUST be defined by a delegate. This is the main relation between an event and a delegate and is described in the section II.18 Defining events of ECMA-335 (CLI) Partitions I to VI:
However, this fact does NOT imply that an event uses a backing delegate field. In truth, an event may use a backing field of any different data structure type of your choice. If you implement an event explicitly in C#, you are free to choose the way you store the event handlers (note that event handlers are instances of the type of the event, which in turn is mandatorily a delegate type---from the previous Observation). But, you can store those event handlers (which are delegate instances) in a data structure such as a
List
or aDictionary
or any other else, or even in a backing delegate field. But don’t forget that it is NOT mandatory that you use a delegate field.In addition to the syntactic and operational properties, there's also a semantical difference.
Delegates are, conceptually, function templates; that is, they express a contract a function must adhere to in order to be considered of the "type" of the delegate.
Events represent ... well, events. They are intended to alert someone when something happens and yes, they adhere to a delegate definition but they're not the same thing.
Even if they were exactly the same thing (syntactically and in the IL code) there will still remain the semantical difference. In general I prefer to have two different names for two different concepts, even if they are implemented in the same way (which doesn't mean I like to have the same code twice).
To understand the differences you can look at this 2 examples
Example with Delegates (in this case, an Action - that is a kind of delegate that doesn't return a value)
To use the delegate, you should do something like this:
This code works well but you could have some weak spots.
For example, if I write this:
with the last line of code, I have overridden the previous behaviors just with one missing
+
(I have used=
instead of+=
)Another weak spot is that every class which uses your
Animal
class can raiseRaiseEvent
just calling itanimal.RaiseEvent()
.To avoid these weak spots you can use
events
in c#.Your Animal class will change in this way:
to call events
Differences:
Notes:
EventHandler is declared as the following delegate:
it takes a sender (of Object type) and event arguments. The sender is null if it comes from static methods.
This example, which uses
EventHandler<ArgsSpecial>
, can also be written usingEventHandler
instead.Refer here for documentation about EventHandler
An Event declaration adds a layer of abstraction and protection on the delegate instance. This protection prevents clients of the delegate from resetting the delegate and its invocation list and only allows adding or removing targets from the invocation list.
Covariance
andContravariance
provide extra flexibility to the delegate objects. On the other hand, an event has no such concepts.Covariance
allows you to assign a method to the delegate where the return type of the method is a class which is derived from the class that specifies the return type of the delegate.Contravariance
allows you to assign a method to the delegate where the parameter type of the method is a base class of the class that is specified as the parameter of the delegate.