C # conhece dois termos delegate
e event
. Vamos começar com o primeiro.
Delegar
A delegate
é uma referência a um método. Assim como você pode criar uma referência a uma instância:
MyClass instance = myFactory.GetInstance();
Você pode usar um delegado para criar uma referência a um método:
Action myMethod = myFactory.GetInstance;
Agora que você tem essa referência a um método, pode chamá-lo através da referência:
MyClass instance = myMethod();
Mas por que você faria? Você também pode ligar myFactory.GetInstance()
diretamente. Nesse caso, você pode. No entanto, há muitos casos em que você não deseja que o restante do aplicativo tenha conhecimento myFactory
ou ligue myFactory.GetInstance()
diretamente.
Uma óbvia é se você quer ser capaz de substituir myFactory.GetInstance()
a myOfflineFakeFactory.GetInstance()
de um lugar central (aka padrão Factory Method ).
Padrão de método de fábrica
Portanto, se você tem uma TheOtherClass
classe e precisa usar a myFactory.GetInstance()
, é assim que o código será exibido sem delegados (você precisará informar TheOtherClass
sobre o tipo da sua myFactory
):
TheOtherClass toc;
//...
toc.SetFactory(myFactory);
class TheOtherClass
{
public void SetFactory(MyFactory factory)
{
// set here
}
}
Se você usar delegados, não precisará expor o tipo da minha fábrica:
TheOtherClass toc;
//...
Action factoryMethod = myFactory.GetInstance;
toc.SetFactoryMethod(factoryMethod);
class TheOtherClass
{
public void SetFactoryMethod(Action factoryMethod)
{
// set here
}
}
Assim, você pode atribuir um delegado a outra classe para usar, sem expor seu tipo a eles. A única coisa que você está expondo é a assinatura do seu método (quantos parâmetros você tem e quais).
"Assinatura do meu método", onde eu ouvi isso antes? O sim, interfaces !!! interfaces descrevem a assinatura de uma classe inteira. Pense nos delegados como descrevendo a assinatura de apenas um método!
Outra grande diferença entre uma interface e um delegado é que, quando você está escrevendo sua classe, não precisa dizer ao C # "esse método implementa esse tipo de delegado". Com interfaces, você precisa dizer "esta classe implementa esse tipo de interface".
Além disso, uma referência de delegado pode (com algumas restrições, veja abaixo) fazer referência a vários métodos (chamados MulticastDelegate
). Isso significa que quando você chama o delegado, vários métodos anexados explicitamente serão executados. Uma referência a objeto sempre pode fazer referência apenas a um objeto.
As restrições para a MulticastDelegate
são que a assinatura (método / delegado) não deve ter nenhum valor de retorno ( void
) e as palavras-chave out
e ref
não é usada na assinatura. Obviamente, você não pode chamar dois métodos que retornam um número e esperam que eles retornem o mesmo número. Uma vez que a assinatura esteja em conformidade, o delegado será automaticamente a MulticastDelegate
.
Evento
Eventos são apenas propriedades (como os campos get; set; properties para instance) que expõem a assinatura ao delegado de outros objetos. Essas propriedades, no entanto, não suportam get; set ;. Em vez disso, eles suportam add; remover;
Então você pode ter:
Action myField;
public event Action MyProperty
{
add { myField += value; }
remove { myField -= value; }
}
Uso na interface do usuário (WinForms, WPF, UWP etc.)
Portanto, agora sabemos que um delegado é uma referência a um método e que podemos ter um evento para informar ao mundo que eles podem nos fornecer seus métodos a serem referenciados por nosso delegado, e somos um botão de interface do usuário: pode perguntar a qualquer pessoa interessada se fui clicado para registrar seu método conosco (por meio do evento exposto). Podemos usar todos os métodos que nos foram dados e consultá-los pelo nosso delegado. E então, vamos esperar ... até que um usuário chegue e clique nesse botão, teremos motivos suficientes para chamar o delegado. E como o delegado faz referência a todos os métodos que nos foram dados, todos esses métodos serão invocados. Não sabemos o que esses métodos fazem, nem sabemos qual classe implementa esses métodos. Só nos preocupamos com o fato de alguém estar interessado em sermos clicados,
Java
Idiomas como Java não têm representantes. Eles usam interfaces. A maneira como eles fazem isso é pedir a qualquer pessoa interessada em 'nos clicar', para implementar uma certa interface (com um determinado método que podemos chamar), e nos fornecer toda a instância que implementa a interface. Mantemos uma lista de todos os objetos que implementam essa interface e podemos chamar seu 'método certo que podemos chamar' sempre que clicamos.