Delegate methods in C#. A practical example
Tags: csharp, dotnet, delegates, generics
Published: 2019-09-13 00:13:02

I was reading a domain drive design PHP [repository](https://github.com/CodelyTV/php-ddd-skeleton) created by [CodelyTv](https://codely.tv) that is a model to create new solutions using this methodology when I found something interesting to perform in futures scenarios. I read the next piece of code:

``` php
use function Lambdish\Phunctional\repeat;

final class Repeater
{
    public static function repeat(callable $function, $quantity): array
    {
        return repeat($function, $quantity);
    }

    public static function repeatLessThan(callable $function, $max): array
    {
        return self::repeat($function, IntegerMother::lessThan($max));
    }

    public static function random(callable $function): array
    {
        return self::repeat($function, IntegerMother::lessThan(5));
    }
}
```

Firstly, this code is a helper class that is used in unit test cases. The [Repeater](https://github.com/CodelyTV/php-ddd-skeleton/blob/master/tests/src/Shared/Domain/Repeater.php) class creates a random objects list using a callable function as a parameter and results are added into the list *N* times. 

Therebefore we can execute random methods as follow:

``` php
Repeater::random(CourseIdMother::creator());
Repeater::random(IntegerMother::random());
```
In the first line, the result is a list with *N* elements resulting of `CourseIdMother::creator()` and in the second line, there is a list with *N* elements of int type. It also exists another method called `repeatLessThan` with which we can specify the max amount of objects that we want to store into the list. 

Coming back to my introduction, I was reading this code when I thought that it is a good scenario to explain how we can use delegates or callable methods.

#Delegate methods - Introduction.

A delegate method is a reference type variable that holds the reference to a method and it can be changed at runtime. It is especially used for implementing events and call-back methods.

There are three steps in defining and using delegates:
1. Declaration of our delegate.
2. Instantiation, creating the delegate’s object.
3. Invocation, where we call a referenced method.

``` csharp
//Declaration
public delegate void WriterDelegate(string text);
class Program
{
    public static void Write(string text)
    {
        Console.WriteLine(text);
    }
 
    static void Main(string[] args)
    {
        //Instantiation
        WriterDelegate writerDelegate = new WriterDelegate(Write);
 
        //Invocation
        writerDelegate("Some example text.");
    }
}
```

Also, C# have two built-in delegates: `Func<T>` and `Action<T>`

Action is a kind of delegates method that it has up to sixteen parameters and it does not return any result. So, we can assign to this delegate only methods with the void return type. 

Otherwise, Func has up to sixteen parameters and it returns a result. In other words, we use the Func delegate only with a method wich result type is other than void.

I do not want to extend this article with theory, but I recommend to check this [documentation](https://code-maze.com/csharp-delegates/#action<t>delegate) in order to understand how we can use Action and Func methods in a simple way. 


# Delegate methods - Example.

Helping by [Generics](https://code-maze.com/csharp-generics/) in C#, we can create a similar random method, as it is shown in the first part of this article, using the Func<T> sending as a parameter.

``` csharp
private static IEnumerable<T> Repeat(Func<T> method, int quantity)
{
   for (int i = 0; i < quantity; i++)
   {
       yield return method();
   }
}
```

With `Repeat(Func<T> method, int quantity)` we can execute *N* times a Func and the result store it into an `IEnumerable<T>`. The entire class `Repeater<T>` results in: 

``` csharp
using System;
using System.Collections.Generic;
using System.Linq;

public class Repeater<T>
{
    private static IEnumerable<T> Repeat(Func<T> method, int quantity)
    {
        for (int i = 0; i < quantity; i++)
        {
            yield return method();
        }
    }

    public static IEnumerable<T> RepeateLessThan(Func<T> method, int max)
    {
        return Repeat(method, IntegerMother.LessThan(max));
    }

    public static IEnumerable<T> Random(Func<T> method)
    {
        return Repeat(method, IntegerMother.LessThan(5));
    }
}
```

It looks very similar than the original code. Finally, we can use the helper `Repeater<T>` class in the following ways:

``` csharp
Repeater<CourseId>.Random(CourseIdMother.Random);
Repeater<int>.Random(IntegerMother.Random);
Repeater<string>.RepeateLessThan(StringMother.Random,20);
```

As we can see, the method generates a objects list executing a `Func<T>`. It always returns an object of the same type indicated in the contract (CourseId in the first example).

Another example of delegate commonly used is the [repository](https://code-maze.com/async-generic-repository-pattern/) pattern with Expressions. We can create a Get method that executes a where sentence defined by another method and it returns an IQueryable object.

``` csharp
public abstract class RepositoryBase<T> : IRepositoryBase<T> where T : class
{
    protected RepositoryContext RepositoryContext { get; set; }
 
    public RepositoryBase(RepositoryContext repositoryContext)
    {
        this.RepositoryContext = repositoryContext;
    }
 
    public IQueryable<T> FindAll()
    {
        return this.RepositoryContext.Set<T>();
    }
 
    public IQueryable<T> FindByCondition(Expression<Func<T, bool>> expression)
    {
        return this.RepositoryContext.Set<T>()
            .Where(expression);
    }
}
```

Using this approach we could send a where sentence created by [LinQ](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/introduction-to-linq-queries) expression as a parameter, as follow:  
``` csharp
await FindByCondition(o => o.Id.Equals(ownerId))             
             .SingleAsync();

await FindByCondition(o => o.Age > 10 && o.Name.Contains(ownerName))             
             .SingleAsync();
```

There are many uses and potential scenarios for delegate methods in C# but this article shows a simple example to understand how we can use this kind of tools that the language provided. 


# Recommended resources.
[Microsoft - Using Delegates](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/delegates/using-delegates)
[Why Delegates](https://buildplease.com/pages/why-delegates/)
[Code Maze - Delegates](https://code-maze.com/csharp-delegates/)