O que é delegado? [fechadas]

152

Estou confuso que qual é o papel real de um delegado?

Fiz essa pergunta muitas vezes em minhas entrevistas, mas não acho que os entrevistadores tenham ficado satisfeitos com a minha resposta.

Alguém pode me dizer a melhor definição, em uma frase, com um exemplo prático?

Naveed
fonte
21
por curiosidade, o que você respondeu para que possamos lhe dizer como você pode corrigi-lo?
Anthony Forloney
6
Acho interessante que esta questão foi encerrada, mas tem 126 votos positivos e 65 pessoas a marcaram como favorita. Parece que, mesmo que seja muito amplo, ainda é uma pergunta muito boa.
Rich

Respostas:

171

Eu gosto de pensar em um delegado como "um ponteiro para uma função". Isso remonta aos dias C, mas a idéia ainda se mantém.

A ideia é que você precise invocar um trecho de código, mas esse trecho de código que você irá invocar não é conhecido até o tempo de execução. Então você usa um "delegado" para esse fim. Os delegados são úteis para coisas como manipuladores de eventos, etc., onde você faz coisas diferentes com base em eventos diferentes, por exemplo.

Aqui está uma referência para C # que você pode ver:

Em C #, por exemplo, digamos que tínhamos um cálculo que queríamos fazer e que queríamos usar um método de cálculo diferente que não conhecíamos até o tempo de execução. Portanto, podemos ter alguns métodos de cálculo como este:

public static double CalcTotalMethod1(double amt)
{
    return amt * .014;
}

public static double CalcTotalMethod2(double amt)
{
    return amt * .056 + 42.43;
}

Poderíamos declarar uma assinatura de delegado como esta:

public delegate double calcTotalDelegate(double amt);

E então poderíamos declarar um método que leva o delegado como um parâmetro como este:

public static double CalcMyTotal(double amt, calcTotalDelegate calcTotal)
{
    return calcTotal(amt);
}

E poderíamos chamar o CalcMyTotalmétodo passando no método delegate que queríamos usar.

double tot1 = CalcMyTotal(100.34, CalcTotalMethod1);
double tot2 = CalcMyTotal(100.34, CalcTotalMethod2);
Console.WriteLine(tot1);
Console.WriteLine(tot2);
dcp
fonte
19
+1 para o aceno para o ponteiro de função simples, mas eficaz em C.
Aiden Bell
3
Uma pergunta relacionada à sua resposta. Como é realmente diferente de chamar uma função da maneira normal? Só por isso não é conhecido em tempo de execução?
Naveed
1
@ NAVEED - consulte a minha edição mais recente, incluí um exemplo. Quanto à chamada de método real, ela não parece diferente de uma chamada de método normal no meu exemplo acima (o calcTotal (amt) está chamando o delegado), mas o poder dos delegados é que você pode usá-los como parâmetros, etc. quando você deseja que um método possa ter um comportamento diferente. Existem muitas outras coisas para as quais você pode usá-las também, este é apenas um exemplo simples. Espero que ajude.
dcp 11/01
Não é conhecido em tempo de execução e é uma função vinculada, e não uma função livre - atribuir um método não estático Fooa um delegado chamará, em this.Foo()vez de uma função estática, como faria um ponteiro de função (em C, você geralmente tem um void*parâmetro extra para passe thispara o ponteiro da função)
Pete Kirkham
1
+1 para o exemplo rápido e eficaz que estabelece semelhanças com ponteiros de função em C / C ++. Muito apreciado!
G21 25/09
19

um delegado é simplesmente um ponteiro de função.
basta colocar o método que você deseja executar no seu delegado. depois, no código, você pode chamar esse método via Invoke.

algum código para demonstrar (escrevi isso da memória para que a sintaxe esteja desativada)

delegate void delMyDelegate(object o);

private void MethodToExecute1(object o)
{
    // do something with object
}

private void MethodToExecute2(object o)
{
    // do something else with object
}

private void DoSomethingToList(delMyDelegate methodToRun)
{
    foreach(object o in myList)
        methodToRun.Invoke(o);
}

public void ApplyMethodsToList()
{
    DoSomethingToList(MethodToExecute1);
    DoSomethingToList(MethodToExecute2);
}
Mladen Prajdic
fonte
16

Retirado daqui

P O que são delegados?
A Quando um objeto recebe uma solicitação, ele pode manipular a solicitação em si ou passar a solicitação para um segundo objeto para executar o trabalho. Se o objeto decidir passar a solicitação, você diz que o objeto encaminhou a responsabilidade de manipular a solicitação para o segundo objeto.

Ou, como um pseudo exemplo fácil: algo envia uma solicitação ao objeto1. O objeto1 encaminha a solicitação e ele próprio para o objeto2 - o delegado. O objeto2 processa a solicitação e faz algum trabalho. (nota: o link acima fornece bons exemplos)

Anthony Forloney
fonte
O exemplo fornecido no link acima não indica corretamente a delegação.
Hardik9850
4

Pense no delegado como uma implementação simplificada do padrão de comando.

Vitaliy Liptchinsky
fonte
4

Um delegado é um objeto que pode se referir a um método. Assim, quando criamos um delegado, estamos criando um objeto que pode conter uma referência a um método. Além disso, o método pode ser chamado através desta referência. Assim, um delegado pode invocar o método ao qual se refere. A principal vantagem de um delegado é que ele permite especificar uma chamada para um método, mas o método realmente chamado é determinado no tempo de execução, não no tempo de compilação.

Delegado Simples

Declaration of delegate:
delegate-modifier delegate return-type delegate-name(parameters)
Implementation of delegate:
Delegate-name delegate-object=new Delegate-name(method of class)

http://knowpacific.wordpress.com/2012/01/26/delegate/

Sandeep Shekhawat
fonte
2

Aqui eu vou explicar delegados, delegados multicast e seu uso. Delegate é um tipo que contém a referência dos métodos em um objeto. Também é referido como um ponteiro de função de segurança de tipo. Podemos dizer que um delegado é um tipo que define uma assinatura de método.

Ao instanciar um delegado, você pode associar sua instância a qualquer método com uma assinatura compatível. Você pode invocar (ou chamar) o método através da instância delegada. Delegados são usados ​​para passar métodos como argumentos para outros métodos. Os manipuladores de eventos nada mais são do que métodos chamados por meio de delegados. As vantagens do uso de delegados são: Encapsular a chamada do método do chamador O uso efetivo do delegado melhora o desempenho do aplicativo Usado para chamar um método de forma assíncrona. Existem algumas propriedades dos delegados que são

Delegates are like C++ function pointers but are type safe.
Delegates allow methods to be passed as parameters.
Delegates can be used to define callback methods.
Delegates can be chained together; for example, multiple methods can be called on a single event.
Methods do not have to match the delegate signature exactly.

delegado público type_of_delegate delegate_name () // Declaration

You can use delegates without parameters or with parameter list
If you are referring to the method with some data type then the delegate which you are declaring should be in the same format. This is why it is referred to as type safe function pointer. Here I am giving an example with String.

O exemplo a seguir mostra uma operação de delegação:

    namespace MyDelegate
    {
        class Program
        {
            private delegate void Show(string s);


            // Create a method for a delegate.
            public static void MyDelegateMethod(string me

ssage)
        {
            System.Console.WriteLine(message);
        }

        static void Main(string[] args)
        {
            Show p = MyDelegateMethod;
            p("My Delegate");
            p.Invoke("My Delegate");
            System.Console.ReadLine();
        }
    }
}

O que é o delegado de difusão seletiva?

É um delegado que mantém a referência de mais de um método. Delegados de difusão seletiva devem conter apenas métodos que retornem nulos, caso contrário, há uma exceção em tempo de execução.

 delegate void MyMulticastDelegate(int i, string s);
 Class Class2
 {
  static void MyFirstDelegateMethod(int i, string s)
  {
    Console.WriteLine("My First Method");
  }

  static void MySecondDelegateMethod(int i, string s)
  {
    Console.WriteLine("My Second Method");
  }

  static void Main(string[] args)
  {
    MyMulticastDelegate Method= new MyMulticastDelegate(MyFirstDelegateMethod);
    Method+= new MyMulticastDelegate (MySecondDelegateMethod);
    Method(1,"Hi");             // Calling 2 Methodscalled
    Method-= new MyMulticastDelegate (MyFirstDelegateMethod);
    Method(2,"Hi");             //Only 2nd Method calling
  }
}

Aqui, o Delegado é adicionado usando o operador + = e removido usando o operador - =.

Tipos de delegado são derivados da classe Delegate no .NET Framework. Tipos de delegados são selados - eles não podem ser derivados. Como o delegado instanciado é um objeto, ele pode ser passado como parâmetro ou atribuído a uma propriedade. Isso permite que um método aceite um delegado como parâmetro e chame o delegado posteriormente. Isso é conhecido como retorno de chamada assíncrono.

Jom George
fonte
1

Uma ótima explicação e implementação prática do padrão Delegado podem ser encontradas nas Classes de encaminhamento de coleções do Google (também, o padrão Decorator).

Carl
fonte
1

No evento, o remetente da comunicação não sabe qual objeto manipulará o evento. Delegar é o tipo que contém a referência do método. Delegate possui assinatura e mantém referência ao método que corresponde à sua assinatura, portanto Delegate é como o tipo de ponteiro de função segura.

button1.Click + = new System.EventHandler (button1_Click) System.EventHandler é declarado como um representante aqui.

Delegate é usado quando você não sabe qual código chamar no tempo de execução. Nesse momento, Delegate é usado para manipular eventos

http://msdn.microsoft.com/en-us/library/ms173171(v=vs.80).aspx

Yogesh
fonte
1

Um objeto delegado é um objeto que outro objeto consulta quando algo acontece nesse objeto. Por exemplo, seu técnico de reparos é o seu delegado se algo acontecer ao seu carro. você vai ao seu técnico e pede que ele conserte o carro para você (embora alguns prefiram consertar o carro eles mesmos, nesse caso, eles são seus próprios delegados).


fonte
1

Um delegado é um objeto que representa um ponteiro para uma função. No entanto, não é um ponteiro de função comum, pois:

1) É orientado a objetos

2) O tipo é seguro, ou seja, pode apenas apontar para um método e você não pode ler o endereço de memória bruto para o qual está apontando

3) É fortemente digitado. Ele só pode apontar para métodos que correspondem às suas assinaturas.

4) Pode apontar para mais de um método ao mesmo tempo.

Refrigerador de água v2
fonte
1

Delegados é usado principalmente com eventos.

A necessidade é:

Você não deseja executar um pedaço de código no momento em que executa o programa. Depois de executar o programa, você deseja executar esse trecho de código sempre que ocorrer um evento.

Exemplo:

  1. Aplicativo de console - o código pode ser executado somente no momento em que você executa o programa. (Escrito dentro do método Principal)
  2. Aplicação do Windows (programação da interface do usuário) - o código pode ser executado ao clicar no botão após a execução do programa.

É o que eles dizem, você não sabe qual método será chamado no momento da compilação. você sabe disso apenas no tempo de execução, quando clica no botão.

Sem delegados, não é possível programar a interface do usuário. Porque você está executando código sempre que o usuário faz eventos que estão clicando no botão, digitando na caixa de texto, selecionando o item da lista suspensa e assim por diante ....

Shathar Khan
fonte
0

Um delegado é algo ao qual uma tarefa está sendo delegada. O principal objetivo da delegação é desacoplar o código e permitir maior flexibilidade e reutilização.

Na programação, e especificamente na programação orientada a objetos, isso significa que, quando um método é chamado para realizar algum trabalho, ele passa o trabalho para o método de outro objeto ao qual ele tem uma referência. A referência pode apontar para qualquer objeto que desejarmos, desde que o objeto esteja em conformidade com um conjunto predefinido de métodos. Chamamos isso de "programação para uma interface" (versus programação para uma implementação de classe concreta). Uma interface é basicamente um modelo genérico e não possui implementação; significa simplesmente uma receita, um conjunto de métodos, pré-condições e pós-condições (regras).

Exemplo simples:

SomeInterface
{
   public void doSomething();
}


SomeImplementation implements SomeInterface
{
   public void doSomething()
   {
      System.err.println("Was it good for you?");
   }

}


SomeCaller
{
   public void doIt(SomeInterface someInterface)
   {
      someInterface.doSomething();
   }
}

Agora você vê que posso usar a implementação que quiser a qualquer momento, sem alterar o código no SomeCaller, porque o tipo que doIt()é passado não é concreto, mas abstrato, pois é uma interface. No mundo Java, isso geralmente é expresso no paradigma de serviço em que você chama um serviço (um objeto que se anuncia como um serviço por meio de uma interface específica) e o serviço chama os delegados para ajudá-lo a fazer seu trabalho. Os métodos do serviço são nomeados como tarefas de granularidade grossa (makePayment (), createNewUser (), etc.), enquanto, internamente, é muito útil se trabalho minucioso através da delegação, com os tipos de delegados sendo interfaces em vez de implementações concretas.

SomeService
{
    SomeInterface someImplementation = ... // assign here
    SomeOtherInterface someOtherImplementation = ... // okay, let's add a second

    public void doSomeWork()
    {
         someImplementation.doSomething();
         someOtherImplementation.doSomethingElse();
    }
}

(Observação: como uma implementação é atribuída está além do escopo desse segmento. Inversão de pesquisa de controle e injeção de dependência.)

Aquarelle
fonte
-2

Embora não seja realmente um "ponteiro de função", um delegado pode parecer com uma linguagem dinâmica como PHP:



$func = 'foo';
$func();

function foo() {
    print 'foo';
}

ou em JavaScript, você pode fazer algo como:


var func = function(){ alert('foo!'); }
func();

mmattax
fonte
2
Este não é um exemplo de delegação. No seu exemplo, você está usando a chamada função de variável, que basicamente procura por uma função com o mesmo nome que a string à qual uma variável se refere. Veja funções variáveis: php.net/manual/pt/functions.variable-functions.php
Aquarelle