Delegate Pisanie delegat generycznych w C# dla początkujących programistów może być wyzwaniem.

A wiesz, że możesz napisać delegaty, które będą asynchroniczne.

Zobaczmy jak takie delegaty napisać :

W C# mamy 4 typy delegat :

  • Takie, które zwracają wartość
  • Takie, które nie zwracają wartości
  • Takie, które nie przyjmują parametrów
  • Takie, które przyjmują określoną ilość parametrów

Jak te 4 typy tłumaczą się typy generyczne :

  • Delegata, która nie przyjmuje parametrów oraz niczego nie zwraca : Action
  • Delegata, która przyjmuje określoną liczbę parametrów oraz niczego nie zwraca : Action<T>
  • Delegata, która nie przyjmuje parametrów, ale zwraca wartość: Func<T>
  • Delegata, która przyjmuje parametry oraz zwraca wartość : Func<T,R>

W praktyce wygląda to tak :

public class GenericDelegatePresentation
{
    // Action
    public void Action(Action action)
    {
        action();
    }

    // Action<Tin>
    public void ActionWithParameter(Action<string> action)
    {
        action("ActionWithParameter executed");
    }

    // Func<Tout>
    public bool FuncThatOnlyReturs(Func<bool> func)
    {
        return func();
    }

    // Func<Tin, Tout>
    public bool FuncThatReturnsAndNeedsParameter(Func<string, bool> func)
    {
        return func("FuncThatReturnsAndNeedsParameter executed");
    }
}

Oto użycie tej klasy w konsoli :

class Program
{
    static void Main(string[] args)
    {
        var presentation = new GenericDelegatePresentation();

        presentation.Action(() => Console.WriteLine("Action executed"));

        presentation.ActionWithParameter((string param) => Console.WriteLine(param));

        presentation.FuncThatOnlyReturs(() => {
            Console.WriteLine("FuncThatOnlyReturs executed");
            return true;
        });

        presentation.FuncThatReturnsAndNeedsParameter((string param) => {
            Console.WriteLine(param);
            return true;
        });
    }
}

Jak zmienić te delegaty na asynchroniczne?  Po pierwsze zawsze musimy zwracać Task w wersji generycznej i nie, a to znaczy, że delegata generyczna Action idzie do kosza. Zostaje nam tylko delegata Func

Jak wyglądają 4 asynchroniczne delegaty :

  • Asynchroniczna Delegata, która nie przyjmuje parametrów oraz niczego nie zwraca : Func<Task>
  • Asynchroniczna  Delegata, która przyjmuje określoną liczbę parametrów oraz niczego nie zwraca : Func<T,Task>
  • Asynchroniczna Delegata, która nie przyjmuje parametrów, ale zwraca wartość: Func<Task<Tresult>>
  • Asynchroniczna  Delegata, która przyjmuje parametry oraz zwraca wartość : Func<T,Task<TResult>>

Przeróbmy kod, abyśmy mieli asynchroniczne delegaty :

public class AsyncGenericDelegatePresentation
{
    public async Task ActionNowFuncTask(Func<Task> task)
    {
        await task();
    }


    public async Task ActionWithParameterNowFuncParameterAndTask(Func<string,Task> task)
    {
        await task("ActionWithParameterNowFuncParameterAndTask executed");
    }

    public async Task<bool> FuncThatOnlyRetursNowFuncTaskGeneric(Func<Task<bool>> func)
    {
        return await func();
    }

    public async Task<bool> FuncThatReturnsAndNeedsParameterNowFuncWihtParameterAndTaskGenric(Func<string, Task<bool>>
        task)
    {
        return await task("FuncThatReturnsAndNeedsParameter executed");
    }
}

Teraz ich użyjmy:

static async Task Main(string[] args)
{
    // Czekaj ponieważ to jest async
    Console.WriteLine();

    var presentation = new AsyncGenericDelegatePresentation();

    await presentation.ActionNowFuncTask(async () =>
        await Task.Run(() => Console.WriteLine("ActionNowFuncTask executed"))
    );

    await presentation.ActionWithParameterNowFuncParameterAndTask(async (string param) =>
        await Task.Run(() => Console.WriteLine(param))
    );

    await presentation.FuncThatOnlyRetursNowFuncTaskGeneric(async () => {
        await Task.Run(() => Console.WriteLine("ActionWithParameterNowFuncParameterAndTask executed"));
        return true;
    });

    await presentation.FuncThatReturnsAndNeedsParameterNowFuncWihtParameterAndTaskGenric
        (async (string param) => {
        await Task.Run(() => Console.WriteLine(param));
        return true;
    });
}

Jak widzisz jest to dobry trening i w sumie także dobre ćwiczenie na rozmowę kwalifikacyjną