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.
Um delegado é um tipo que encapsula com segurança um método, semelhante a um ponteiro de função em C e C++. No entanto, ao contrário dos ponteiros de função de C, delegados são orientados a objeto, fortemente tipados e seguros. O exemplo a seguir declara um delegado nomeado Callback
que pode encapsular um método que usa uma cadeia de caracteres como um argumento e retorna nulo:
public delegate void Callback(string message);
Um objeto delegado normalmente é construído fornecendo o nome do método que o delegado encapsula ou com uma expressão lambda. Um delegado pode ser invocado uma vez instanciado dessa maneira. A invocação de um representante chama o método anexado à instância delegada. Os parâmetros passados para o delegado pelo chamador são passados para o método. O delegado retorna o valor de retorno, se houver, do método. Por exemplo:
// Create a method for a delegate.
public static void DelegateMethod(string message)
{
Console.WriteLine(message);
}
// Instantiate the delegate.
Callback handler = DelegateMethod;
// Call the delegate.
handler("Hello World");
Os tipos de delegado são derivados da Delegate classe no .NET. Os tipos de delegado são selados; eles não podem ser derivados, e não é possível derivar classes personalizadas de Delegate. Como o delegado instanciado é um objeto, ele pode ser passado como um argumento ou atribuído a uma propriedade. Um método pode aceitar um delegado como um parâmetro e chamar o delegado posteriormente. Isso é conhecido como um retorno de chamada assíncrono e é um método comum de notificação de um chamador quando um processo longo é concluído. Quando um delegado é usado dessa forma, o código que usa o delegado não precisa de nenhum conhecimento da implementação do método que está sendo usado. A funcionalidade é semelhante à oferecida pelas interfaces de encapsulamento.
Outro uso comum de chamadas de retorno é definir um método de comparação personalizada e passar esse delegado para um método de classificação. Ele permite que o código do chamador se torne parte do algoritmo de classificação. O seguinte método de exemplo usa o Del
tipo como um parâmetro:
public static void MethodWithCallback(int param1, int param2, Callback callback)
{
callback("The number is: " + (param1 + param2).ToString());
}
Em seguida, você pode passar o delegado criado no exemplo anterior para esse método:
MethodWithCallback(1, 2, handler);
E receber a seguinte saída para o console:
The number is: 3
MethodWithCallback
não precisa acessar o console diretamente, nem ser projetado pensando em um console. O que MethodWithCallback
faz é preparar uma cadeia de caracteres e passar a cadeia de caracteres para outro método. Um método delegado pode usar qualquer número de parâmetros.
Quando um delegado é construído para encapsular um método de instância, o delegado faz referência à instância e ao método. Um delegado não tem conhecimento do tipo de instância, exceto pelo método que envolve. Um delegado pode se referir a qualquer tipo de objeto, desde que haja um método nesse objeto que corresponda à assinatura do delegado. Quando um delegado é construído para encapsular um método estático, ele faz referência apenas ao método. Considere as seguintes declarações:
public class MethodClass
{
public void Method1(string message) { }
public void Method2(string message) { }
}
Juntamente com a estática DelegateMethod
mostrada anteriormente, agora temos três métodos que você pode encapsular em uma Del
instância.
Um delegado pode chamar mais de um método quando invocado, conhecido como multicasting. Para adicionar um método extra à lista de métodos do delegado — a lista de invocação — basta adicionar dois delegados usando os operadores de adição ou de atribuição de adição ('+' ou '+ ='). Por exemplo:
var obj = new MethodClass();
Callback d1 = obj.Method1;
Callback d2 = obj.Method2;
Callback d3 = DelegateMethod;
//Both types of assignment are valid.
Callback allMethodsDelegate = d1 + d2;
allMethodsDelegate += d3;
O allMethodsDelegate
contém três métodos em sua lista de invocação —Method1
Method2
e DelegateMethod
. Os três delegados originais, d1
e d2
d3
, permanecem inalterados. Quando allMethodsDelegate
é invocado, todos os três métodos são chamados em ordem. Se o delegado usar parâmetros de referência, a referência será passada sequencialmente para cada um dos três métodos, e quaisquer alterações por um método ficarão visíveis para o próximo método. Quando qualquer um dos métodos gera uma exceção que não é capturada dentro do método, essa exceção é passada para o chamador do delegado. Nenhum método subsequente na lista de invocação é chamado. Se o delegado tiver um valor retornado e/ou parâmetros externos, ele retornará o valor retornado e os parâmetros do último método invocado. Para remover um método da lista de invocação, use os operadores de subtração ou atribuição de subtração (-
ou -=
). Por exemplo:
//remove Method1
allMethodsDelegate -= d1;
// copy AllMethodsDelegate while removing d2
Callback oneMethodDelegate = (allMethodsDelegate - d2)!;
Como os tipos de delegado são derivados de System.Delegate
, os métodos e as propriedades definidos por essa classe podem ser invocados pelo delegado. Por exemplo, para localizar o número de métodos na lista de invocação de um delegado, você pode escrever:
int invocationCount = d1.GetInvocationList().GetLength(0);
Delegados com mais de um método em sua lista de invocação derivam de MulticastDelegate, que é uma subclasse de System.Delegate
. O código anterior funciona em ambos os casos porque ambas as classes dão suporte GetInvocationList
.
Delegados multicast são amplamente usados na manipulação de eventos. Os objetos de origem do evento enviam notificações de evento para objetos de destinatário que se registraram para receber esse evento. Para se registrar em um evento, o destinatário cria um método projetado para manipular o evento e, em seguida, cria um delegado para esse método e passa o delegado para a origem do evento. A origem chama o delegado quando o evento ocorre. O delegado chama então o método de manipulação de eventos no destinatário, fornecendo os dados do evento. A origem do evento define o tipo de delegado para um determinado evento. Para obter mais informações, consulte Eventos.
A comparação de delegados de dois tipos diferentes atribuídos no tempo de compilação resulta em um erro de compilação. Se as instâncias delegadas forem estaticamente do tipo System.Delegate
, a comparação será permitida, mas retornará false em tempo de execução. Por exemplo:
delegate void Callback1();
delegate void Callback2();
static void method(Callback1 d, Callback2 e, System.Delegate f)
{
// Compile-time error.
Console.WriteLine(d == e);
// OK at compile-time. False if the run-time type of f
// is not the same as that of d.
Console.WriteLine(d == f);
}