Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
No artigo anterior, você viu que cria tipos de delegado específicos usando a delegate palavra-chave.
A classe de Delegado abstrata fornece a infraestrutura para a invocação e acoplamento fraco. Os tipos delegados concretos tornam-se muito mais úteis adotando e impondo segurança de tipo para os métodos que são adicionados à lista de invocação de um objeto delegado. Quando você usa a delegate palavra-chave e define um tipo de delegado concreto, o compilador gera esses métodos.
Na prática, isso levaria à criação de novos tipos de delegado sempre que você precisar de uma assinatura de método diferente. Este trabalho pode ficar entediante depois de um tempo. Cada novo recurso requer novos tipos de delegado.
Felizmente, isso não é necessário. A estrutura do .NET Core contém vários tipos que você pode reutilizar sempre que precisar de tipos delegados. Essas são definições genéricas para que você possa declarar personalizações quando precisar de novas declarações de método.
O primeiro desses tipos é o Action tipo e várias variações:
public delegate void Action();
public delegate void Action<in T>(T arg);
public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);
// Other variations removed for brevity.
O in modificador no argumento de tipo genérico é abordado no artigo sobre covariância.
Há variações do Action delegado que contêm até 16 argumentos, como Action<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16>.
É importante que essas definições usem argumentos genéricos diferentes para cada um dos argumentos delegados: isso oferece flexibilidade máxima. Os argumentos do método não precisam ser, mas podem ser do mesmo tipo.
Use um dos Action tipos para qualquer tipo delegado que tenha um tipo de retorno nulo.
A estrutura também inclui vários tipos de delegado genéricos que você pode usar para tipos delegados que retornam valores:
public delegate TResult Func<out TResult>();
public delegate TResult Func<in T1, out TResult>(T1 arg);
public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);
// Other variations removed for brevity
O out modificador no argumento de tipo genérico de resultado é abordado no artigo sobre covariância.
Há variações do Func delegado com até 16 argumentos de entrada, como Func<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,TResult>.
O tipo do resultado é sempre o último parâmetro de tipo em todas as Func declarações, por convenção.
Use um dos Func tipos para qualquer tipo delegado que retorne um valor.
Há também um tipo Predicate<T> especializado para um delegado que retorna um teste em um único valor:
public delegate bool Predicate<in T>(T obj);
Você pode observar que, para qualquer Predicate tipo, existe um tipo estruturalmente equivalente Func , por exemplo:
Func<string, bool> TestForString;
Predicate<string> AnotherTestForString;
Você pode pensar que esses dois tipos são equivalentes. Eles não são. Essas duas variáveis não podem ser usadas de forma intercambiável. Uma variável de um tipo não pode ser atribuída ao outro tipo. O sistema de tipos C# usa os nomes dos tipos definidos, não a estrutura.
Todas essas definições de tipo delegado na Biblioteca do .NET Core devem significar que você não precisa definir um novo tipo de delegado para qualquer novo recurso criado que exija delegados. Essas definições genéricas devem fornecer todos os tipos delegados necessários na maioria das situações. Você pode simplesmente instanciar um desses tipos com os parâmetros de tipo necessários. No caso de algoritmos que podem se tornar genéricos, esses delegados podem ser usados como tipos genéricos.
Isso deve economizar tempo e minimizar o número de novos tipos que você precisa criar para trabalhar com delegados.
No próximo artigo, você verá vários padrões comuns para trabalhar com delegados na prática.