C_Sharp_Language

C Sharp TutorialC Sharp .NET Compiler Platform (Roslyn)C Sharp 3.0 FeaturesC Sharp 4.0 FeaturesC Sharp 5.0 FeaturesC Sharp 6.0 FeaturesC Sharp 7.0 FeaturesC Sharp Access ModifiersC Sharp Access network shared folder with username and passwordC Sharp Accessing DatabasesC Sharp Action FiltersC Sharp Aliases of built-in typesC Sharp an overview of collectionsC Sharp Anonymous typesC Sharp ArraysC Sharp ASP.NET IdentityC Sharp AssemblyInfo.cs ExamplesC Sharp Async-AwaitC Sharp Async/await, Backgroundworker, Task and Thread ExamplesC Sharp Asynchronous SocketC Sharp AttributesC Sharp Authentication handlerC Sharp BackgroundWorkerC Sharp BigIntegerC Sharp Binary SerializationC Sharp BindingListC Sharp Built-in TypesC Sharp CachingC Sharp CastingC Sharp Checked and UncheckedC Sharp CLSCompliantAttributeC Sharp Code ContractsC Sharp Code Contracts and AssertionsC Sharp Collection InitializersC Sharp Comments and regionsC Sharp Common String OperationsC Sharp Conditional StatementsC Sharp Constructors and FinalizersC Sharp Creating Own MessageBox in Windows Form ApplicationC Sharp Creational Design PatternsC Sharp Cryptography (System.Security.Cryptography)C Sharp Data AnnotationC Sharp DateTime MethodsC Sharp DelegatesC Sharp Dependency InjectionC Sharp DiagnosticsC Sharp Dynamic typeC Sharp EnumC Sharp Equality OperatorC Sharp Equals and GetHashCodeC Sharp EventsC Sharp Exception HandlingC Sharp Expression TreesC Sharp Extension MethodsC Sharp File and Stream I/OC Sharp FileSystemWatcherC Sharp Func delegatesC Sharp Function with multiple return valuesC Sharp Functional ProgrammingC Sharp Garbage Collector in .NETC Sharp Generating Random NumbersC Sharp Generic Lambda Query BuilderC Sharp GenericsC Sharp Getting Started: Json with C SharpC Sharp GuidC Sharp Handling FormatException when converting string to other typesC Sharp Hash FunctionsC Sharp ICloneableC Sharp IComparableC Sharp IDisposable interfaceC Sharp IEnumerableC Sharp ILGeneratorC Sharp ImmutabilityC Sharp Implementing Decorator Design PatternC Sharp Implementing Flyweight Design PatternC Sharp Import Google ContactsC Sharp Including Font ResourcesC Sharp IndexerC Sharp InheritanceC Sharp Initializing PropertiesC Sharp INotifyPropertyChanged interfaceC Sharp InterfacesC Sharp InteroperabilityC Sharp IQueryable interfaceC Sharp IteratorsC Sharp KeywordsC Sharp Lambda expressionsC Sharp Lambda ExpressionsC Sharp LINQ QueriesC Sharp LINQ to Objects



C Sharp Delegates

From WikiOD

Remarks[edit | edit source]

Summary[edit | edit source]

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>[edit | edit source]

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[edit | edit source]

Named delegate types can be declared using the delegate keyword.

Invoking delegates[edit | edit source]

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[edit | edit source]

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[edit | edit source]

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.

Declaring a delegate type[edit | edit source]

The following syntax creates a delegate type with name NumberInOutDelegate, representing a method which takes an int and returns an int.

public delegate int NumberInOutDelegate(int input);

This can be used as follows:

public static class Program
{
    static void Main()
    {
        NumberInOutDelegate square = MathDelegates.Square;
        int answer1 = square(4); 
        Console.WriteLine(answer1); // Will output 16

        NumberInOutDelegate cube = MathDelegates.Cube;
        int answer2 = cube(4);
        Console.WriteLine(answer2); // Will output 64            
    }
}

public static class MathDelegates
{
    static int Square (int x)
    {
        return x*x;
    }

    static int Cube (int x)
    {
        return x*x*x;
    }
}

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:

public delegate TTo Converter<in TFrom, out TTo>(TFrom input);

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:

public delegate void EventHandler<in TEventArgs>(object sender, TEventArgs e);

Instead, use an invariant generic type:

public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);

Also supported are delegates where some parameters are modified by ref or out, as in:

public delegate bool TryParser<T>(string input, out T result);

(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, Action and Predicate delegate types[edit | edit source]

The System namespace contains Func<..., TResult> delegate types with between 0 and 15 generic parameters, returning type TResult.

private void UseFunc(Func<string> func)
{
    string output = func(); // Func with a single generic type parameter returns that type
    Console.WriteLine(output);
}

private void UseFunc(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.

private void UseAction(Action action)
{
    action(); // The non-generic Action has no parameters
}

private void UseAction(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 true
var predicateReturnsTrue = predicate("abc");
var funcReturnsTrue = func("abc");

// Both of these return false
var 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)[edit | edit source]

Addition + and subtraction - operations can be used to combine delegate instances. The delegate contains a list of the assigned delegates.

using System;
using System.Reflection;
using System.Reflection.Emit;

namespace DelegatesExample {
    class MainClass {
        private delegate void MyDelegate(int a);

        private static void PrintInt(int a) {
            Console.WriteLine(a);
        }

        private static void PrintType<T>(T a) {
            Console.WriteLine(a.GetType());
        }

        public static void Main (string[] args)
        {
            MyDelegate d1 = PrintInt;
            MyDelegate d2 = PrintType;

            // Output:
            // 1
            d1(1);

            // Output:
            // System.Int32
            d2(1);

            MyDelegate d3 = d1 + d2;
            // Output:
            // 1
            // System.Int32
            d3(1);

            MyDelegate d4 = d3 - d2;
            // Output:
            // 1
            d4(1);

            // Output:
            // True
            Console.WriteLine(d1 == d4);
        }
    }
}

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.

    class Program
    {
        public delegate int Transformer(int x);

        static void Main(string[] args)
        {
            Transformer t = Square;
            t += Cube;
            Console.WriteLine(t(2));  // O/P 8 
        }

        static int Square(int x) { return x * x; }

        static int Cube(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[edit | edit source]

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:

public static class DelegateExtensions
{
    public static void SafeInvoke(this Delegate del,params object[] args)
    {
        var exceptions = new List<Exception>();

        foreach (var handler in del.GetInvocationList())
        {
            try
            {
                handler.Method.Invoke(handler.Target, args);
            }
            catch (Exception ex)
            {
                exceptions.Add(ex);
            }
        }

        if(exceptions.Any())
        {
            throw new AggregateException(exceptions);
        }
    }
}

public class Test
{
    public delegate void SampleDelegate();

    public void Run()
    {
        SampleDelegate delegateInstance = this.Target2;
        delegateInstance += this.Target1;

        try
        {
            delegateInstance.SafeInvoke();
        } 
        catch(AggregateException ex)
        {
            // Do any exception handling here
        }
    }

    private void Target1()
    {
        Console.WriteLine("Target 1 executed");
    }

    private void Target2()
    {
        Console.WriteLine("Target 2 executed");
        throw new Exception();
    }
}

This outputs:

Target 2 executed
Target 1 executed

Invoking directly, without SaveInvoke, would only execute Target 2.

Delegate Equality[edit | edit source]

Calling .Equals() on a delegate compares by reference equality:

Action action1 = () => Console.WriteLine("Hello delegates");
Action action2 = () => Console.WriteLine("Hello delegates");
Action action1Again = action1;

Console.WriteLine(action1.Equals(action1)) // True
Console.WriteLine(action1.Equals(action2)) // False
Console.WriteLine(action1Again.Equals(action1)) // True

These rules also apply when doing += or -= on a multicast delegate, for example when subscribing and unsubscribing from events.

Underlying references of named method delegates[edit | edit source]

When assigning named methods to delegates, they will refer to the same underlying object if:

They are the same instance method, on the same instance of a class

They are the same static method on a class

public class Greeter
{
    public void WriteInstance()
    {
        Console.WriteLine("Instance");
    }

    public static void WriteStatic()
    {
        Console.WriteLine("Static");
    }
}

// ...

Greeter greeter1 = new Greeter();
Greeter greeter2 = new Greeter();

Action instance1 = greeter1.WriteInstance;
Action instance2 = greeter2.WriteInstance;
Action instance1Again = greeter1.WriteInstance;

Console.WriteLine(instance1.Equals(instance2)); // False
Console.WriteLine(instance1.Equals(instance1Again)); // True

Action @static = Greeter.WriteStatic;
Action staticAgain = Greeter.WriteStatic;

Console.WriteLine(@static.Equals(staticAgain)); // True

Assigning a named method to a delegate[edit | edit source]

Named methods can be assigned to delegates with matching signatures:

public static class Example
{
    public static int AddOne(int input)
    {
        return input + 1;
    }
}

Func<int,int> addOne = Example.AddOne

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[edit | edit source]

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[edit | edit source]

Delegates can be used as typed function pointers:

class FuncAsParameters
{
  public void Run()
  {
    DoSomething(ErrorHandler1);
    DoSomething(ErrorHandler2);
  }

  public bool ErrorHandler1(string message)
  {
    Console.WriteLine(message);
    var shouldWeContinue = ...  
    return shouldWeContinue;
  }

  public bool ErrorHandler2(string message)
  {
    // ...Write message to file...
    var shouldWeContinue = ...  
    return shouldWeContinue;
  }

  public void DoSomething(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 continue
        return;
      }
    }
  }
}

Closure inside a delegate[edit | edit source]

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

delegate int testDel();
static void Main(string[] args)
{
    int foo = 4;
    testDel myClosure = delegate()
    {
        return foo;
    };
    int bar = myClosure();

}

Example taken from Closures in .NET.

Encapsulating transformations in funcs[edit | edit source]

public class MyObject{
    public DateTime? TestDate { get; set; }

    public Func<MyObject, bool> DateIsValid = myObject => myObject.TestDate.HasValue && myObject.TestDate > DateTime.Now;

    public void DoSomething(){
        //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:

public void CheckForIntegrity(){
    if(ShipDateIsValid(this) && TestResultsHaveBeenIssued(this) && !TestResultsFail(this)){
        SendPassingTestNotification();
    }
}

Credit:Stack_Overflow_Documentation