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 { get; set; }
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<int, int, string, object> OnClickAction;
Isso nos livra de ter que declarar um delegate primeiro como em:
public delegate void OnClickHandler(int x, int y, string nome, object 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<int, int, string, object, int> OnClickFunction;
Lembrando que seu método precisa ter esses requerimentos, então você faria algo como:
int MyFunction(int x, int y, string nome, object 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.
Comentários (0)