attributes
?
access-modifier
?
|
new?
|
delegate
|
[
void | type
]
|
delegate
-
name
(
parameter-list
);
|
A delegate is a type that defines a method signature, so that delegate instances can hold and invoke a method or list of methods that match its signature. A delegate declaration consists of a name and a method signature.[1]
Here’s an example:
delegate bool Filter(string s);
This declaration lets you create delegate instances that can hold and
invoke methods that return bool
and have a single
string parameter. In the following example a
Filter
is created that holds the
FirstHalf-OfAlphabet
method. You then pass the
Filter
to the Display
method,
which invokes the Filter
:
class Test { static void Main( ) { Filter f = new Filter(FirstHalfOfAlphabet); Display(new String [] {"Ant","Lion","Yak"}, f); } static bool FirstHalfOfAlphabet(string s) { return "N".CompareTo(s) > 0; } static void Display(string[] names, Filter f) { int count = 0; foreach(string s in names) if(f(s)) // invoke delegate Console.WriteLine("Item {0} is {1}", count++, s); } }
If a
delegate
has a void return type, it is a multicast
delegate that can hold and invoke multiple methods. In this example,
we declare a simple delegate called MethodInvoker
,
which can hold and then invoke the Foo
and
Goo
methods sequentially. The
+=
method creates a new delegate by adding the
right delegate operand to the left delegate operand.
delegate void MethodInvoker( ); class Test { static void Main( ) { new Test( ); // prints "Foo","Goo" } Test( ) { MethodInvoker m = null; m += new MethodInvoker(Foo); m += new MethodInvoker(Goo); m( ); } void Foo( ) { Console.WriteLine("Foo"); } void Goo( ) { Console.WriteLine("Goo"); } }
A delegate can also be removed from another delegate using the
-=
operator:
Test { MethodInvoker m = null; m += new MethodInvoker(Foo); m -= new MethodInvoker(Foo); // m is now null }
Delegates are invoked in the order they are added. Note that
the
+=
and
-=
operations on a delegate are thread-safe.
To work with the .NET runtime, C# compiles +=
and
-=
operations made on a delegate to the static
Combine
and Remove
methods of
the System.Delegate
class. Delegates with a void
return type alias System.MulticastDelegate
.
Delegates with a non-void return type alias (the single-cast)
System.Delegate
, because it doesn’t make
sense to return a value from multiple methods.
A delegate is behaviorally similar to a C function pointer (or Delphi closure), but delegates can hold multiple methods and hold the instance associated with each non-static method. In addition, delegates, like all other C# constructs used outside unsafe blocks, are type-safe and secure, which means you’re protected from pointing to the wrong type of method or a method that you don’t have permission to access.
A
problem that can be solved with
a delegate can also be solved with an interface. For instance, here
is how to solve the filter problem using an
IFilter
interface:
interface IFilter { bool Filter(string s); } class Test { class FirstHalfOfAlphabetFilter : IFilter { public bool Filter(string s) { return ("N".CompareTo(s) > 0); } } static void Main( ) { FirstHalfOfAlphabetFilter f = new FirstHalfOfAlphabetFilter( ); Display(new string [] {"Ant", "Lion", "Yak"}, f); } static void Display(string[] names, IFilter f) { int count = 0; foreach (string s in names) if (f.Filter(s)) Console.WriteLine("Item {0} is {1}", count++, s); } }
In this case, the problem was slightly more elegantly handled with a delegate, but generally delegates are best used for event handling.
[1] The signature of a delegate method includes its return type and also allows the use of a params modifier in its parameter list, expanding the list of elements that characterize an ordinary method signature. The actual name of the target method is irrelevant to the delegate.
18.118.20.156