Delegates enable scenarios that other languages-C++, Pascal, Modula, and others-have addressed with function pointers. Unlike C++ function pointers, delegates are fully object oriented; unlike C++ pointers to member functions, delegates encapsulate both an object instance and a method.
A delegate declaration defines a class that extends the class System.Delegate. A delegate instance encapsulates a method-a callable entity. For instance methods, a callable entity consists of an instance and a method on the instance. For static methods, a callable entity consists of just a method. If you have a delegate instance and an appropriate set of arguments, you can invoke the delegate with the arguments.
An interesting and useful property of a delegate is that it does not know or care about the class of the object that it references. Any object will do; all that matters is that the method's signature matches the delegate's. This makes delegates perfectly suited for "anonymous" invocation.
A delegate-declaration is a type-declaration that declares a new delegate type.
[attributes] [delegate-modifiers] delegate result-type identifier ( [formal-parameter-list] );
It is an error for the same modifier to appear multiple times in a delegate declaration.
The new modifier is only permitted on delegates declared within another type. It specifies that the delegate hides an inherited member by the same name.
The public, protected, internal, and private modifiers control the accessibility of the delegate type. Depending on the context in which the delegate declaration occurs, some of these modifiers may not be permitted.
The formal-parameter-list identifies the signature of the delegate, and the result-type indicates the return type of the delegate. The signature and return type of the delegate must exactly match the signature and return type of any method that the delegate type encapsulates. Delegate types in C# are name equivalent, not structurally equivalent. Two different delegates types that have the same signature and return type are considered different delegate types.
A delegate type is a class type that is derived from System.Delegate. Delegate types are implicitly sealed: it is not permissible to derive any type from a delegate type. It is also not permissible to derive a non-delegate class type from System.Delegate. Note that System.Delegate is not itself a delegate type, it is a class type that all delegate types derive from.
C# provides special syntax for delegate instantiation and invocation. Except for instantiation, any operation that can be applied to a class or class instance can also be applied to a delegate class or instance. In particular, it is possible to access members of the System.Delegate type via the usual member access syntax.
Combinable delegate types
Delegate types are classified into two kinds: combinable and non-combinable. A combinable delegate type must satisfy the following conditions:
• The declared return type of the delegate must be void.
• None of the parameters of the delegate type can be declared as output parameters.
A run-time exception occurs if an attempt is made to combine two instances of a non-combinable delegate types unless one or the other is null.
Although delegates behave in most ways like other classes, C# provides special syntax for instantiating a delegate instance. A delegate-creation-expression is used to create a new instance of a delegate. The newly created delegate instance then refers to either:
• The static method referenced in the delegate-creation-expression, or
• The target object (which cannot be null) and instance method referenced in the delegate-creation-expression, or
• Another delegate
Once instantiated, delegate instances always refer to the same target object and method.
Delegates can be combined using the addition operator, and one delegate can be removed from another using the subtraction operator. A delegate instance created by combining two or more (non-null) delegate instances is called a multicast delegate instance. For any delegate instance, the invocation list of the delegate is defined as the ordered list of non-multicast delegates that would be invoked if the delegate instance were invoked.
• For a non-multicast delegate instance, the invocation list consists of the delegate instance itself.
• For a multi-cast delegate instance that was created by combining two delegates, the invocation list is the formed by concatenating the invocation lists of the two operands of the addition operation that formed the multi-cast delegate.
Read more about multicast delegate...
C# provides special syntax for invoking a delegate. When a non-multicast delegate is invoked, it invokes the method that the delegate refers to with the same arguments, and returns the same value that the referred to method returns. If an exception occurs during the invocation of a delegate, and the exception is not caught within the method that was invoked, the search for an exception catch clause continues in the method that called the delegate, as if that method had directly called the method that the delegate referred to.
Invocation of a multi-cast delegate proceeds by invocation each of the delegates on the invocation list, in order. Each call is passed the same set of arguments. If the delegate includes reference parameters, each method invocation will occur with a reference to the same variable; changes to that variable by one method in the invocation list will be "seen" by any later methods in the invocation list.
If an exception occurs during processing of the invocation of a multicast delegate, and the exception is not caught within the method that was invoked, the search for an exception catch clause continues in the method that called the delegate, and any methods later in the invocation list are not invoked.