# Delegates

* A delegate is a type that represents references to methods with a particular parameter list and return type.&#x20;
* When you instantiate a delegate, you can associate its instance with any method with a compatible signature and return type.&#x20;
* You can invoke (or call) the method through the delegate instance.
* Delegates are used to pass methods as arguments to other methods.
* Event Handlers are nothing more than methods that are invoked through delegates.

## Types of Delegate

* Single Delegate - used to invoke single method
* Multicast Delegate - used to invoke multiple methods
* Generic Delegate
  * Func Delegate
  * Action Delegate
  * Predicate Delegate

{% tabs %}
{% tab title="Single-cast Delegate" %}
```csharp
public delegate int CalculateDel(int a, int b);    // Decalaration

public class DelegateExample {
    public void Sum(int a, int b) {
        return a + b;
    }
    public void Difference(int a, int b) {
        return a - b;
    }
}

class Program {
    static void Main() {
        DelegateExample obj = new DelegateExample();
        
        // Instantiation
        CalculateDel sumDel = new CalculateDel(obj.Sum);
        CalculateDel diffDel = new CalculateDel(obj.Difference);
        
        // Invocation
        Console.WriteLine("Sum : " + sumDel(10, 5));
        Console.WriteLine("Difference : " + diffDel(10, 5));
    }
}
```
{% endtab %}

{% tab title="Multi-cast Delegate" %}
```csharp
public delegate void CalculateDel(int a, int b);    // Decalaration

public class DelegateExample {
    public void Sum(int a, int b) {
        Console.WriteLine("Sum : " + (a + b));
    }
    public void Difference(int a, int b) {
        Console.WriteLine("Difference : " + (a - b));
    }
}

class Program {
    static void Main() {
        DelegateExample obj = new DelegateExample();
        
        // Instantiation
        CalculateDel multicastDel = new CalculateDel(obj.Sum);
        multicastDel += new CalculateDel(obj.Difference);
        
        // OR
        // CalculateDel multicastDel1 = new CalculateDel(obj.Sum);
        // CalculateDel multicastDel2 = new CalculateDel(obj.Difference);
        // CalculateDel multicastDel = multicastDel1 + multicastDel2;
        
        // Invocation
        multicastDel.Invoke(10, 5);
    }
}
```
{% endtab %}
{% endtabs %}

{% hint style="info" %}
#### Multi-cast Delegate

* All the methods will be invoked in the same order as it is added.
* If the delegate has return type other than void then the returned value of the last invoked method will be returned.
* If the delegate has an out parameter then the value of the out parameter will be the value assigned by the last invoked method.
{% endhint %}

### Generic Delegate

#### Func Delegate

* Func delegate must return a value.
* Func delegate can have 0 to 16 input parameters.
* Func delegate does not allow ref and out parameters.
* Func delegate must have 1 out parameter for the result.

```csharp
int Add(int a, int b) {
    return a + b;
}

Func<int, int, int> addFuncDel = Add;    // Generic Func Delegate
int result = addFuncDel.Invoke(10, 5);
Console.WriteLine(result);
```

#### Action Delegate

* Action delegate does not return any value.
* Action delegate can have 0 to 16 input parameters.
* Action delegate does not allow ref and out parameters.
* It can be used with Anonymous method and Lambda Expression.

```csharp
int Difference(int a, int b) {
    return a - b;
}

Action<int, int> diffFuncDel = Difference;    // Generic Action Delegate
int result = diffFuncDel.Invoke(10, 5);
Console.WriteLine(result);
```

#### Predicate Delegate

* Predicate delegate takes one input parameter and boolean return type.
* Anonymous method and Lambda Expressioin can be assigned to Predicate delegate.

```csharp
bool isEven(int i) {
    if(i % 2 == 0)
        return true;
    return false;
}

Predicate<int> isEvenPredicateDel = isEven;    // Generic Predicate Delegate
bool result = isEvenPredicateDel.Invoke(100);
Console.WriteLine(result);
```

## Things to Remember

* Delegates are like C++ function pointers but are type safe.
* Delegates allow methods to be passed as parameters.
* Delegates are used in event handling for defining callback methods.
* Delegates can be chained together i.e. these allow defining a set of methods that executed as a single unit.
* Once a delegate is created, the method it is associated will never changes because delegates are immutable in nature.
* Delegates provide a way to execute methods at run-time.

{% hint style="info" %}
A **publisher** is an object that contains the definition of the event and the delegate.
{% endhint %}
