A delegate is used to provide
a decoupling of caller from callee;
that is, a delegate points to a given method (instance or static) in
a class, and callers can call through the delegate without having to
know the target of the call. In many respects, the delegate is
conceptually similar to the C/C++ function
pointer, with a number of important advantages. A delegate
is strongly typed, meaning that only methods that match the
delegate's declared signature are acceptable when
constructing the delegate instance, and the compiler enforces the
delegate's declared signature when called. A
delegate can distinguish between a static and an instance method.
This avoids the C++ application associated with pointers to member
functions, which require a literal pointer to the
object upon which to invoke the method.
Delegates are usually constructed by the language compiler, varying
in syntax from language to language. In C#, the construct
public delegate void CallbackDelegate(int
param1, string param2); declares a new
type that derives from the Delegate type (its
immediate superclass is actually
MulticastDelegate). This new
CallbackDelegate type is also declared with a
constructor (to take the method to call when the delegate is invoked)
and an Invoke method (to do the actual call),
along with asynchronous versions of Invoke (the
BeginInvoke and EndInvoke
methods).
In many cases, you will want to use delegates as an
invocation chain, where a single call to the
delegate should result in a series of calls against a collection of
delegate targets. (This is most easily seen in
.NET's publish-subscribe event-handling
idiom—C#'s event keyword.)
To achieve this, Delegate contains static methods
allowing delegates to combine into a single delegate instance that
calls into multiple delegate targets. The Combine(
) method takes two existing delegate instances (with
identical signatures) and returns a single delegate instance that
calls both targets when invoked. (There is another form of
Combine( ) that takes an array of delegates
instead of just a pair.) Remove( ) does the
opposite of Combine( ), removing a delegate from
the multicast call chain. (See the
MulticastDelegate entry for more information on
multicast delegates.)
Delegates can also be invoked using the DynamicInvoke(
) method, without knowing the actual concretely generated
Delegate subtype. This method expects an array of
object references, whose type should match those of the expected
parameters to the delegate. If any of the parameters to
DynamicInvoke( ) do not match those expected by
the target method, an exception is thrown. Delegates can also be
constructed in the same generic fashion using one of the overloaded
forms of CreateDelegate( ).
Delegates can be invoked either synchronously or asynchronously. To
invoke a delegate synchronously (that is, block until the call(s)
return), simply use the delegate as if it is a method, as shown in
Section 4.1. The call to a delegate is executed completely
before execution resumes in the calling method. Should you wish the
call to the delegate to occur in parallel with the calling method,
use the BeginInvoke method to start execution and
the EndInvoke method to wait for the asynchronous
delegate call's completion (if it
hasn't finished by the time the
EndInvoke call is made). If any of the
delegate's parameters are declared as
ref or out parameters, these
parameters will be available on the parameter list to
EndInvoke.
public abstract class Delegate : ICloneable, System.Runtime.Serialization.ISerializable {
// Protected Constructors
protected Delegate(object target, string method);
protected Delegate(Type target, string method);
// Public Instance Properties
public MethodInfo Method{get; }
public object Target{get; }
// Public Static Methods
public static Delegate Combine(Delegate[ ] delegates);
public static Delegate Combine(Delegate a, Delegate b);
public static Delegate CreateDelegate(Type type, System.Reflection.MethodInfo method);
public static Delegate CreateDelegate(Type type, object target, string method);
public static Delegate CreateDelegate(Type type, object target, string method,
bool ignoreCase);
public static Delegate CreateDelegate(Type type, Type target, string method);
public static Delegate Remove(Delegate source, Delegate value);
public static Delegate RemoveAll(Delegate source, Delegate value);
public static bool operator !=(Delegate d1, Delegate d2);
public static bool operator = =(Delegate d1, Delegate d2);
// Public Instance Methods
public virtual object Clone( );
// implements ICloneable
public object DynamicInvoke(object[ ] args);
public override bool Equals(object obj);
// overrides object
public override int GetHashCode( );
// overrides object
public virtual Delegate[ ] GetInvocationList( );
public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
// implements ISerializable
// Protected Instance Methods
protected virtual Delegate CombineImpl(Delegate d);
protected virtual object DynamicInvokeImpl(object[ ] args);
protected virtual MethodInfo GetMethodImpl( );
protected virtual Delegate RemoveImpl(Delegate d);
}