Co to jest delegat? [Zamknięte]

152

Nie wiem, jaka jest rzeczywista rola delegata?

Pytanie to zadawano mi wielokrotnie w wywiadach, ale nie sądzę, żeby ankieterzy byli zadowoleni z mojej odpowiedzi.

Czy ktoś może mi podać najlepszą definicję jednym zdaniem z praktycznym przykładem?

Naveed
źródło
21
z ciekawości, co odpowiedziałeś, abyśmy mogli Ci powiedzieć, jak możesz to poprawić?
Anthony Forloney,
6
Uważam za interesujące, że to pytanie zostało zamknięte, ale ma 126 głosów za, a 65 osób oznaczyło je jako ulubione. Wygląda na to, że nawet jeśli jest zbyt szerokie, to nadal bardzo dobre pytanie.
Rich

Odpowiedzi:

171

Lubię myśleć o delegacie jako o „wskaźniku do funkcji”. To sięga czasów C, ale pomysł wciąż jest aktualny.

Chodzi o to, że musisz mieć możliwość wywołania fragmentu kodu, ale ten fragment kodu, który zamierzasz wywołać, nie jest znany do czasu wykonania. W tym celu używasz więc „delegata”. Delegaci przydają się do takich rzeczy, jak programy obsługi zdarzeń i tym podobne, gdy na przykład wykonujesz różne czynności w oparciu o różne zdarzenia.

Oto odniesienie do języka C #, na które możesz spojrzeć:

Na przykład w C # załóżmy, że mamy obliczenie, które chcieliśmy wykonać i chcieliśmy użyć innej metody obliczeniowej, której nie znamy do czasu uruchomienia. Więc możemy mieć kilka metod obliczeniowych, takich jak ta:

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

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

Moglibyśmy zadeklarować podpis delegata w następujący sposób:

public delegate double calcTotalDelegate(double amt);

Następnie moglibyśmy zadeklarować metodę, która przyjmuje delegata jako parametr w następujący sposób:

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

Moglibyśmy wywołać CalcMyTotalmetodę przekazującą metodę delegata, której chcieliśmy użyć.

double tot1 = CalcMyTotal(100.34, CalcTotalMethod1);
double tot2 = CalcMyTotal(100.34, CalcTotalMethod2);
Console.WriteLine(tot1);
Console.WriteLine(tot2);
dcp
źródło
19
+1 za ukłon w stronę prostego, ale skutecznego wskaźnika funkcji w C.
Aiden Bell
3
Jedno pytanie związane z Twoją odpowiedzią. Czym naprawdę się różni od wywoływania funkcji w normalny sposób? Tylko z tego powodu nie jest znany w czasie wykonywania?
Naveed
1
@NAVEED - odwołaj się do mojej ostatniej edycji, zamieściłem przykład. Jeśli chodzi o rzeczywiste wywołanie metody, nie wygląda to inaczej niż normalne wywołanie metody w powyższym przykładzie (funkcja calcTotal (amt) wywołuje delegata), ale moc delegatów polega na tym, że można ich używać jako parametrów, itp., gdy chcesz, aby metoda miała inne zachowanie. Jest wiele innych rzeczy, do których możesz ich użyć, to tylko prosty przykład. Mam nadzieję, że to pomoże.
dcp
Nie jest znana w czasie wykonywania i jest funkcją powiązaną, a nie funkcją swobodną - przypisanie Foodelegatowi metody niestatycznej spowoduje wywołanie this.Foo()zamiast funkcji statycznej, jak zrobiłby to wskaźnik funkcji (w C często masz dodatkowy void*parametr do przejść thisdo wskaźnika funkcji)
Pete Kirkham
1
+1 za szybki i skuteczny przykład ustalania podobieństw ze wskaźnikami funkcji w C / C ++. Bardzo cenione!
G21
19

delegat jest po prostu wskaźnikiem funkcji.
po prostu przypisz metodę, którą chcesz uruchomić delegata. później w kodzie możesz wywołać tę metodę za pomocą Invoke.

jakiś kod do zademonstrowania (napisał to z pamięci, więc składnia może być wyłączona)

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
źródło
16

Zaczerpnięte stąd

P Kim są delegaci?
A Gdy obiekt otrzymuje żądanie, może sam je obsłużyć lub przekazać je do drugiego obiektu, aby wykonać pracę. Jeśli obiekt zdecyduje się przekazać żądanie dalej, mówisz, że obiekt przeniósł odpowiedzialność za obsługę żądania na drugi obiekt.

Lub, jako prosty pseudo przykład: coś wysyła żądanie do obiektu1. object1 następnie przekazuje żądanie i siebie do object2 - delegata. object2 przetwarza żądanie i wykonuje jakąś pracę. (uwaga: link powyżej zawiera dobre przykłady)

Anthony Forloney
źródło
Przykład podany w powyższym linku nie przedstawia poprawnie delegacji.
Hardik9850
4

Pomyśl o delegacie jako o uproszczonej implementacji wzorca polecenia.

Vitaliy Liptchinsky
źródło
4

Delegat to obiekt, który może odwoływać się do metody. Tak więc, kiedy tworzymy delegata, tworzymy obiekt, który może przechowywać odniesienie do metody. Ponadto metodę można wywołać za pomocą tego odwołania. W ten sposób delegat może wywołać metodę, do której się odnosi. Główną zaletą delegata jest to, że pozwala nam określić wywołanie metody, ale metoda faktycznie wywołana jest określana w czasie wykonywania, a nie w czasie kompilacji.

Prosty delegat

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
źródło
2

Tutaj mam zamiar wyjaśnić delegatów, delegatów multiemisji i ich użycie. Delegat jest typem, który przechowuje odwołanie do metody (y) w obiekcie. Jest również określany jako wskaźnik funkcji bezpiecznego typu. Można powiedzieć, że delegat to typ, który definiuje sygnaturę metody.

Podczas tworzenia wystąpienia delegata można skojarzyć jego wystąpienie z dowolną metodą z zgodnym podpisem. Możesz wywołać (lub wywołać) metodę za pośrednictwem wystąpienia delegata. Delegaci służą do przekazywania metod jako argumentów do innych metod. Programy obsługi zdarzeń to nic innego jak metody wywoływane przez delegatów. Zalety korzystania z delegatów to: Hermetyzacja wywołania metody z obiektu wywołującego Efektywne użycie delegata poprawia wydajność aplikacji Służy do asynchronicznego wywoływania metody. Istnieją pewne właściwości delegatów

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.

public delegate type_of_delegate delegate_name () // Deklaracja

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.

Poniższy przykład przedstawia operację delegata:

    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();
        }
    }
}

Co to jest delegat multiemisji?

Jest to delegat, który zawiera odniesienie do więcej niż jednej metody. Delegaci multiemisji muszą zawierać tylko metody, które zwracają void, w przeciwnym razie istnieje wyjątek czasu wykonywania.

 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
  }
}

Tutaj Delegat jest dodawany za pomocą operatora + = i usuwany za pomocą operatora - =.

Typy delegatów pochodzą z klasy Delegate w programie .NET Framework. Typy delegatów są zapieczętowane - nie można ich wyprowadzić. Ponieważ utworzony delegat jest obiektem, można go przekazać jako parametr lub przypisać do właściwości. Dzięki temu metoda może zaakceptować delegata jako parametr i wywołać delegata w późniejszym czasie. Nazywa się to asynchronicznym wywołaniem zwrotnym.

Jom George
źródło
1

Świetne wyjaśnienie i praktyczną implementację wzorca Delegate można znaleźć w Google Collections Forwarding Classes (również we wzorcu Decorator).

Carl
źródło
1

W przypadku komunikacji nadawca nie wie, który obiekt obsłuży zdarzenie. Delegat to typ, który zawiera odwołanie do metody. Delegat ma podpis i zawiera odniesienie do metody, która pasuje do jego podpisu, więc delegat jest podobny do wskaźnika funkcji bezpiecznej typu.

button1.Click + = new System.EventHandler (button1_Click) System.EventHandler jest tutaj zadeklarowany jako delegat.

Delegat jest używany, gdy nie wiesz, który kod wywołać w czasie wykonywania, więc w tym czasie delegat jest używany do obsługi zdarzeń

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

Yogesh
źródło
1

Obiekt delegata to obiekt, z którym inny obiekt konsultuje się, gdy coś się w tym obiekcie dzieje. Na przykład osoba zajmująca się naprawą jest Twoim delegatem, jeśli coś stanie się z Twoim samochodem. udajesz się do swojego mechanika i prosisz go, aby naprawił samochód za Ciebie (chociaż niektórzy wolą naprawić samochód samodzielnie, w takim przypadku są ich własnym delegatem).


źródło
1

Delegat to obiekt, który reprezentuje wskaźnik do funkcji. Jednak nie jest to zwykły wskaźnik funkcji, ponieważ:

1) Jest zorientowany obiektowo

2) Czy typ jest bezpieczny, tj. Może wskazywać tylko na metodę i nie możesz odczytać surowego adresu pamięci, na który wskazuje

3) Jest mocno wpisany na maszynie. Może wskazywać tylko metody, które pasują do jego sygnatur.

4) Może wskazywać na więcej niż jedną metodę w tym samym czasie.

Chłodnica wodna v2
źródło
1

Delegaci jest używany głównie w przypadku wydarzeń.

Potrzeba:

Nie chcesz wykonywać fragmentu kodu w czasie uruchamiania programu. Po uruchomieniu programu chcesz wykonać ten fragment kodu za każdym razem, gdy wystąpi zdarzenie.

Przykład:

  1. Aplikacja konsolowa - kod można wykonać tylko w momencie uruchomienia programu. (Napisane w głównej metodzie)
  2. Aplikacja Windows (programowanie interfejsu użytkownika) - kod można wykonać po naciśnięciu przycisku po uruchomieniu programu.

Tak mówią, nie wiesz, która metoda zostanie wywołana w czasie kompilacji. znasz to tylko w czasie wykonywania, czyli po kliknięciu przycisku.

Bez delegatów programowanie interfejsu użytkownika nie jest możliwe. Ponieważ wykonujesz kod za każdym razem, gdy użytkownik wykonuje zdarzenia, które klika przycisk, wpisuje w polu tekstowym, wybiera element listy rozwijanej i tak dalej ...

Shathar Khan
źródło
0

Delegat to osoba, do której delegowane jest zadanie. Głównym celem delegowania jest oddzielenie kodu i umożliwienie większej elastyczności i ponownego wykorzystania.

W programowaniu, a szczególnie w programowaniu obiektowym, oznacza to, że gdy metoda jest wywoływana w celu wykonania jakiejś pracy, przekazuje ją ona do metody innego obiektu, do którego się odwołuje. Odniesienie może wskazywać na dowolny obiekt, który chcemy, pod warunkiem, że jest on zgodny z predefiniowanym zestawem metod. Nazywamy to „programowaniem do interfejsu” (w przeciwieństwie do programowania do konkretnej implementacji klasy). Interfejs jest w zasadzie ogólnym szablonem i nie ma implementacji; oznacza po prostu przepis, zbiór metod, warunków wstępnych i warunków końcowych (reguł).

Prosty przykład:

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();
   }
}

Teraz widzisz, że mogę w dowolnym momencie użyć dowolnej implementacji bez zmiany kodu w SomeCaller, ponieważ doIt()przekazywany typ nie jest konkretny, ale raczej abstrakcyjny, ponieważ jest to interfejs. W świecie Java jest to często wyrażane w paradygmacie usługi, w którym wywołujesz usługę (obiekt reklamujący się jako usługa za pośrednictwem określonego interfejsu), a następnie usługa wzywa delegatów, aby pomogli jej wykonać swoją pracę. Metody usługi są nazywane jako zadania gruboziarniste (makePayment (), createNewUser () itp.), Podczas gdy wewnętrznie robi dużo, jeśli działa drobiazgowo poprzez delegację, przy czym typy delegatów są interfejsami zamiast konkretnych implementacji.

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

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

(Uwaga: sposób przypisywania implementacji wykracza poza zakres tego wątku. Odwrócenie kontroli i iniekcji zależności w wyszukiwaniu).

Aquarelle
źródło
-2

Chociaż nie jest to „wskaźnik funkcji”, delegat może wyglądać tak, jakby był to język dynamiczny, taki jak PHP:



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

function foo() {
    print 'foo';
}

lub w JavaScript możesz zrobić coś takiego:


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

mmattax
źródło
2
To nie jest przykład delegacji. W swoim przykładzie używasz tak zwanej funkcji zmiennej, która zasadniczo szuka funkcji o tej samej nazwie, co ciąg, do którego odnosi się zmienna. Zobacz funkcje zmiennych: php.net/manual/en/functions.variable-functions.php
Aquarelle