2

delegates genéricos Action<> e Func<> em C#

#.NET Core
Willams Sousa
Willams Sousa

O que é um delegate?


Delegate é um mecanismo que permite 'terceirizar' parte de um processo.


Motivação:


Uma biblioteca de interface com o usuário permite criar botões, inputs, menus etc.. Como permitir os usuários da biblioteca execute ações quando um botão for clicado?


Não é possível implementar o método OnClick porque não se sabe de antemão o que é pra fazer quando o evento ocorrer. Usando delegates podemos permitir o registro de métodos que vão atender a esse evento.


Um exemplo pode ser visto a seguir:


using System;


class Button

{

    public delegate void OnClickHandler(object sender);


    public OnClickHandler OnClick;


    public string Name { getset; }



    void InternalOnClick()

    {

        OnClick(this);

    }

}


class Program

{

    static void Main(string[] args)

    {

        Button button = new Button();

        button.Name = "OK";


        button.OnClick = MyOnClick;

    }


    static void MyOnClick(object sender)

    {

        Button button = (Button)sender;


        Console.Write($"Name: {button.Name}");

    }

}


O delegate precisa ser exatamente igual a função que você que passar. No exemplo acima, uma vez que o delegate é do tipo void something(object something), o método do usuário deve ser void something(object something). Se tentar usar void something() ou int something() não funciona.


No código acima a classe Button precisou criar um delegate com o tipo de retorno e tipo(s) de paramentro(s) desejados e só então criar uma propriedade com desse tipo que mais tarde o usuário vai atribuir um método a ele.


Para casos onde não estamos interessados em definir delegates próprios, podemos usar Action (para os casos onde o retorno é void) e Func (para os casos onde deve retornar algo).


Assim, o código acima poderia usar um Action:


public Action<object> OnClick;


Action permite até 16 parâmetros. Se você precisasse de uma ação que vai receber dois inteiros (a posição x,y do clique talvez?), uma string (o nome do botão talvez?) e um objeto, então você faria:


public Action<intintstringobject> OnClickAction;


Isso nos livra de ter que declarar um delegate primeiro como em:


 public delegate void OnClickHandler(int xint ystring nomeobject sender);

public OnClickHandler OnClickAction;


E o Func<>? É a mesma coisa, mas o último carinha da lista será o retorno. Então se OnClick precisa retornar um inteiro, ficaria assim:


 public Func<intintstringobjectint> OnClickFunction;


Lembrando que seu método precisa ter esses requerimentos, então você faria algo como:


int MyFunction(int xint ystring nomeobject sender)

 {

        // dosomething

}


E registraria assim:


 button.OnClickFunction = MyFunction;


Quando usamos delegate é importante manter eles privados e fornecer um método que encapsula seu registro. Assim, um método como RegisterOnClick poderia ser usado no exemplo acima. Uma maneira melhor de fazer isso é usando a palavra reservada event, mas isso fica pra seus estudos. A intenção desse artigo é ativar a curiosidade para pesquisar mais a respeito e criar a base para entender códigos mais complexos do ASP.NET, tais como paralelismo.



Como um adendo, vejamos como algo parecido é usado em uma linguagem não orientada a objetos como C


void qsort(void *base, size_t nitems, size_t size, int (*comparar)(const void *, const void*))


Essa é função da libc (linguagem C) que implementa o algoritmo de ordenação quicksort. Uma vez que o autor da função não sabe que tipo você tá querendo ordenar e muito menos como que ele deve comparar um item com o outro, ele pede que o usuario forneça uma função para comparar dois items, assim, dentro da implementação do qsort será chamada a função comparar que o usuário escreveu. . O nome dessa técnica é 'função callback' e em C isso é usado de maneira direita, pois C permite ponteiros para funções. Legal, né?


Em C#, como acabamos de aprender, a gente teria uma classe QuickSort e uma propriedade onde o usuário pode registrar a função que compara dois items, algo como Comparar = MyComparer(). Claro que tem outras técnicas para esse caso específico, como a interface IComparable, mas esse é outro tema!


Então é isso, agora quando você ver algum código usando esses Action e Func sabe mais ou menos do que se trata.

0
39

Comentários (0)

Tento ser um sujeito legal e gosto de aprender linguagens de programação.

Brasil