The example delegate instance is executed in the same way as the Square method. A delegate instance literally acts as a delegate for the caller: the caller invokes the
delegate, and then the delegate calls the target method. This indirection decouples
the caller from the target method.
You can declare a generic delegate type, and in that case you may specify that the type is covariant (out) or contravariant (in) in some of the type arguments. For example:
Like other generic types, generic delegate types can have constraints, such as where TFrom : struct, IConvertible where TTo : new().
Avoid co- and contravariance for delegate types that are meant to be used for multicast delegates, such as event handler types. This is because concatenation (+) can fail if the run-time type is different from the compile-time type because of the variance. For example, avoid:
(sample use TryParser<decimal> example = decimal.TryParse;), or delegates where the last parameter has the params modifier. Delegate types can have optional parameters (supply default values). Delegate types can use pointer types like int* or char* in their signatures or return types (use unsafe keyword). A delegate type and its parameters can carry custom attributes.
The Func<T, TResult>, Action and Predicate delegate types
The System namespace contains Func<..., TResult> delegate types with between 0 and 15 generic parameters, returning type TResult.
privatevoidUseFunc(Func<string> func){string output =func();// Func with a single generic type parameter returns that type
Console.WriteLine(output);}privatevoidUseFunc(Func<int,int,string> func){string output =func(4,2);// Func with multiple generic type parameters takes all but the first as parameters of that type
Console.WriteLine(output);}
The System namespace also contains Action<...> delegate types with different number of generic parameters (from 0 to 16). It is similar to Func<T1, .., Tn>, but it always returns void.
privatevoidUseAction(Action action){action();// The non-generic Action has no parameters}privatevoidUseAction(Action<int,string> action){action(4,"two");// The generic action is invoked with parameters matching its type arguments}
Predicate<T> is also a form of Func but it will always return bool. A predicate is a way of specifying a custom criteria. Depending on the value of the input and the logic defined within the predicate, it will return either true or false. Predicate<T> therefore behaves in the same way as Func<T, bool> and both can be initialized and used in the same way.
Predicate<string> predicate = s => s.StartsWith("a");Func<string,bool> func = s => s.StartsWith("a");// Both of these return truevar predicateReturnsTrue =predicate("abc");var funcReturnsTrue =func("abc");// Both of these return falsevar predicateReturnsFalse =predicate("xyz");var funcReturnsFalse =func("xyz");
The choice of whether to use Predicate<T> or Func<T, bool> is really a matter of opinion. Predicate<T> is arguably more expressive of the author's intent, while Func<T, bool> is likely to be familiar to a greater proportion of C# developers.
In addition to that, there are some cases where only one of the options is available, especially when interacting with another API. For example List<T> and Array<T> generally take Predicate<T> for their methods, while most LINQ extensions only accept Func<T, bool>.
Combine Delegates (Multicast Delegates)
Addition + and subtraction - operations can be used to combine delegate instances. The delegate contains a list of the assigned delegates.
In this example d3 is a combination of d1 and d2 delegates, so when called the program outputs both 1 and System.Int32 strings.
Combining delegates with non void return types:
If a multicast delegate has a nonvoid return type, the caller receives the return value
from the last method to be invoked. The preceding methods are still called, but their
return values are discarded.
classProgram{publicdelegateintTransformer(int x);staticvoidMain(string[] args){Transformer t = Square;
t += Cube;
Console.WriteLine(t(2));// O/P 8 }staticintSquare(int x){return x * x;}staticintCube(int x){return x*x*x;}}
t(2) will call first Square and then Cube. The return value of Square is discarded and return value of the last method i.e. Cube is retained.
Safe invoke multicast delegate
Ever wanted to call a multicast delegate but you want the entire invokation list to be called even if an exception occurs in any in the chain. Then you are in luck, I have created an extension method that does just that, throwing an AggregateException only after execution of the entire list completes:
publicstaticclassDelegateExtensions{publicstaticvoidSafeInvoke(thisDelegate del,paramsobject[] args){var exceptions =newList<Exception>();foreach(var handler in del.GetInvocationList()){try{
handler.Method.Invoke(handler.Target, args);}catch(Exception ex){
exceptions.Add(ex);}}if(exceptions.Any()){thrownewAggregateException(exceptions);}}}publicclassTest{publicdelegatevoidSampleDelegate();publicvoidRun(){SampleDelegate delegateInstance =this.Target2;
delegateInstance +=this.Target1;try{
delegateInstance.SafeInvoke();}catch(AggregateException ex){// Do any exception handling here}}privatevoidTarget1(){
Console.WriteLine("Target 1 executed");}privatevoidTarget2(){
Console.WriteLine("Target 2 executed");thrownewException();}}
This outputs:
Target 2 executed
Target 1 executed
Invoking directly, without SaveInvoke, would only execute Target 2.
Delegate Equality
Calling .Equals() on a delegate compares by reference equality:
Example.AddOne takes an int and returns an int, its signature matches the delegate Func<int,int>. Example.AddOne can be directly assigned to addOne because they have matching signatures.
Assigning to a delegate by lambda
Lambdas can be used to create anonymous methods to assign to a delegate:
Func<int,int> addOne = x => x+1;
Note that the explicit declaration of type is required when creating a variable this way:
var addOne = x => x+1;// Does not work
Passing delegates as parameters
Delegates can be used as typed function pointers:
classFuncAsParameters{publicvoidRun(){DoSomething(ErrorHandler1);DoSomething(ErrorHandler2);}publicboolErrorHandler1(string message){
Console.WriteLine(message);var shouldWeContinue =...return shouldWeContinue;}publicboolErrorHandler2(string message){// ...Write message to file...var shouldWeContinue =...return shouldWeContinue;}publicvoidDoSomething(Func<string,bool> errorHandler){// In here, we don't care what handler we got passed!...if(...error...){if(!errorHandler("Some error occurred!")){// The handler decided we can't continuereturn;}}}}
Closure inside a delegate
Closures are inline anonymous methods that have the ability to use Parent method variables and other anonymous methods which are defined in the parent's scope.
In essence, a closure is a block of code which can be executed at a
later time, but which maintains the environment in which it was first
created - i.e. it can still use the local variables etc of the method
which created it, even after that method has finished executing.
**-- Jon Skeet**
delegateinttestDel();staticvoidMain(string[] args){int foo =4;testDel myClosure =delegate(){return foo;};int bar =myClosure();}
publicclassMyObject{publicDateTime? TestDate {get;set;}publicFunc<MyObject,bool> DateIsValid = myObject => myObject.TestDate.HasValue && myObject.TestDate > DateTime.Now;publicvoidDoSomething(){//We can do this:if(this.TestDate.HasValue &&this.TestDate > DateTime.Now){CallAnotherMethod();}//or this:if(DateIsValid(this)){CallAnotherMethod();}}}
In the spirit of clean coding, encapsulating checks and transformations like the one above as a Func can make your code easier to read and understand. While the above example is very simple, what if there were multiple DateTime properties each with their own differing validation rules and we wanted to check different combinations? Simple, one-line Funcs that each have established return logic can be both readable and reduce the apparent complexity of your code. Consider the below Func calls and imagine how much more code would be cluttering up the method:
A delegate type is a type representing a particular method signature. An instance of this type refers to a particular method with a matching signature. Method parameters may have delegate types, and so this one method to be passed a reference to another method, which may then be invoked
In-built delegate types: Action<...>, Predicate<T> and Func<...,TResult>
The System namespace contains Action<...>,Predicate<T> and Func<...,TResult> delegates, where the "..." represents between 0 and 16 generic type parameters (for 0 parameters, Action is non-generic).
Func represents methods with a return type matching TResult, and Action represents methods without a return value (void). In both cases, the additional generic type parameters match, in order, the method parameters.
Predicate represents method with boolean return type, T is input parameter.
Custom delegate types
Named delegate types can be declared using the delegate keyword.
Invoking delegates
Delegates can be invoked using the same syntax as methods: the name of the delegate instance, followed by parentheses containing any parameters.
Assigning to delegates
Delegates can be assigned to in the following ways:
Assigning a named method
Assigning an anonymous method using a lambda
Assigning a named method using the delegate keyword.
Combining delegates
Multiple delegate objects can be assigned to one delegate instance by using the + operator. The - operator can be used to remove a component delegate from another delegate.