Що таке делегат? [зачинено]


152

Мене плутає, що яка фактична роль делегата?

Мене багато разів мені задавали це питання в інтерв'ю, але я не думаю, що інтерв'юери були задоволені моєю відповіддю.

Хтось може сказати мені найкраще визначення, в одному реченні, на практичному прикладі?


21
з цікавості, що ви відповіли, щоб ми могли сказати вам, як ви можете виправити це?
Ентоні Форлоні

6
Мені здається цікавим, що це питання було закрито, але нараховується 126 відгуків, і 65 людей відзначили його фаворитом. Здається, навіть якщо вона занадто широка, це все ще дуже гарне питання.
Багатий

Відповіді:


171

Мені подобається думати про делегата як про "вказівник на функцію". Це повертається до C днів, але ідея все-таки дотримується.

Ідея полягає в тому, що вам потрібно мати можливість викликати фрагмент коду, але той фрагмент коду, який ви збираєтеся викликати, не відомий до часу виконання. Таким чином, ви використовуєте для цього "делегат". Делегати корисні для таких речей, як обробники подій, і таких, де ви робите різні речі на основі різних подій, наприклад.

Ось посилання на C #, яку ви можете подивитися:

Наприклад, у C #, скажімо, у нас був розрахунок, який ми хотіли зробити, і ми хотіли використовувати інший метод розрахунку, про який ми не знаємо до часу виконання. Тож у нас може бути пара таких методів розрахунку:

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

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

Ми можемо оголосити підпис делегата на зразок цього:

public delegate double calcTotalDelegate(double amt);

І тоді ми могли б оголосити метод, який приймає делегата як такий параметр:

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

І ми могли б назвати CalcMyTotalметод, що передає метод делегата, який ми хотіли використати.

double tot1 = CalcMyTotal(100.34, CalcTotalMethod1);
double tot2 = CalcMyTotal(100.34, CalcTotalMethod2);
Console.WriteLine(tot1);
Console.WriteLine(tot2);

19
+1 за кивок на простий, але ефективний вказівник функції C.
Ейден Белл

3
Одне запитання, що стосується вашої відповіді. Чим він насправді відрізняється від виклику функції у звичайний спосіб? Просто через це невідомо під час виконання?
Naveed

1
@NAVEED - зверніться до моєї останньої редакції, я включив приклад. Що стосується фактичного виклику методу, він не виглядає відмінним від звичайного виклику методу в моєму прикладі вище (calcTotal (amt) викликає делегата), але сила делегатів полягає в тому, що ви можете використовувати їх як параметри, і т.д., коли ви хочете, щоб метод міг мати різну поведінку. Є багато інших речей, для яких ви також можете їх використовувати, це лише простий приклад. Сподіваюся, що це допомагає.
dcp

Це невідомо під час виконання, і це пов'язана функція, а не вільна функція - призначення нестатичного методу Fooделегату буде викликати, this.Foo()а не статичну функцію, як це робив би покажчик функції (у C, ви часто маєте додатковий void*параметр для перейти thisдо покажчика функції)
Піт Кіркхем

1
+1 для швидкого та ефективного прикладу встановлення подібності з покажчиками функцій у C / C ++. Цінується!
G21

19

делегат - це просто вказівник функції.
просто поставте вам призначити метод, який ви хочете запустити свого делегата. потім пізніше в коді ви можете викликати цей метод через Invoke.

якийсь код для демонстрації (записав це з пам'яті, щоб синтаксис був відключений)

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

16

Взято звідси

Q Що таке делегати?
A Коли об'єкт отримує запит, об’єкт може або сам обробляти запит, або передавати запит другому об'єкту для виконання роботи. Якщо об'єкт вирішив передати запит, ви скажете, що об'єкт передав відповідальність за обробку запиту на другий об'єкт.

Або, як простий псевдоприклад: щось надсилає запит на object1. object1 потім пересилає запит і сам на object2 - делегат. object2 обробляє запит і виконує певну роботу. (зверніть увагу: посилання вище дає хороші приклади)


Приклад, наведений у посиланні вище, неправильно констатує делегування.
Hardik9850


4

Делегат - це об'єкт, який може посилатися на метод. Таким чином, коли ми створюємо делегата, ми створюємо об’єкт, який може містити посилання на метод. Крім того, метод може бути викликаний за допомогою цієї посилання. Таким чином, делегат може викликати метод, на який він посилається. Основна перевага делегата полягає в тому, що він дозволяє нам вказати виклик методу, але фактично викликаний метод визначається під час виконання, а не під час компіляції.

Простий делегат

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/


2

Тут я збираюся пояснити делегатів, делегатів з декількома розсилками та їх використання. Делегат - це тип, який містить об'єкт (и) посилання на об'єкт. Його також називають покажчиком безпечної функції типу. Можна сказати, що делегат - це тип, який визначає підпис методу.

Коли ви створюєте екземпляр делегата, ви можете пов’язати його примірник із будь-яким методом із сумісним підписом. Ви можете викликати (або викликати) метод через екземпляр делегата. Делегати використовуються для передачі методів як аргументів іншим методам. Обробники подій - це не що інше, як методи, які викликаються через делегатів. Переваги використання делегатів полягають у тому, що інкапсуляція виклику методу від абонента Ефективне використання делегата покращує продуктивність програми, що використовується для асинхронного виклику методу. Є деякі властивості делегатів

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.

публічний делегат type_of_delegate delegate_name () // Декларація

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.

У наступному прикладі показана операція делегування:

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

Що таке багатоадресний делегат?

Це делегат, який містить посилання на більш ніж один метод. Делегати для багатоадресної передачі повинні містити лише методи, які повертають недійсність, інакше є виняток під час виконання.

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

Тут Делегат додається за допомогою оператора + = та видаляється за допомогою оператора - =.

Типи делегатів походять від класу Delegate в .NET Framework. Типи делегата запечатані - їх неможливо отримати. Оскільки створений делегат є об'єктом, він може передаватися як параметр або присвоюватися властивості. Це дозволяє методу прийняти делегата як параметр і викликати делегата через деякий пізній час. Це відоме як асинхронний зворотний зв'язок.


1

Чудове пояснення та практичну реалізацію шаблону Delegate можна знайти в Класах переадресації колекцій Google (також, в якості шаблону Decorator).


1

У повідомленні про подію відправник не знає, який об’єкт буде обробляти подію. Делегат - це тип, який містить посилання на метод. Делегат має підпис і посилається на метод, який відповідає його підпису, так що Делегат - як безпечний вказівник функції.

button1.Click + = new System.EventHandler (button1_Click) System.EventHandler декларується як делегат тут.

Делегат використовується, коли ви не знаєте, до якого коду слід викликати час запуску. Тож у цей час Делегат використовується для обробки подій

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


1

Об'єкт делегата є об'єкт, інший об'єкт консультується , коли що - то відбувається в цьому об'єкті. Наприклад, ваш ремонтник - ваш делегат, якщо щось трапиться з вашим автомобілем. Ви заїжджаєте до свого ремонтника і просите його поправити машину на вас (хоча деякі вважають за краще самостійно відремонтувати машину; в такому випадку вони є власним делегатом своєї машини).


1

Делегат - це об'єкт, який представляє вказівник на функцію. Однак це не звичайний покажчик функції в тому, що він:

1) Орієнтована на об'єкти

2) Чи безпечний тип, тобто він може вказувати лише на метод, і ви не можете прочитати необроблену адресу пам'яті, на яку вказує

3) Сильно набраний. Він може вказувати лише на методи, які відповідають його підписам.

4) Може вказувати на кілька методів одночасно.


1

Делегати в основному використовуються з подіями.

Необхідність:

Ви не хочете виконувати фрагмент коду під час запуску програми. Після запуску програми ви хочете виконувати цей фрагмент коду кожного разу, коли відбувається подія.

Приклад:

  1. Додаток консолі - код можна виконати лише в момент запуску програми. (Написано всередині Основний метод)
  2. Додаток Windows (програмування інтерфейсу користувача) - код можна виконати при натисканні кнопки після запуску програми.

Це те, що вони кажуть, ви не знаєте, який метод буде викликати під час компіляції. ви знаєте це лише під час виконання, коли натискаєте кнопку.

Без делегатів неможливе програмування інтерфейсу користувача. Тому що ви виконуєте код щоразу, коли користувач робить події, які натискає кнопку, набираючи текстове поле, вибираючи елемент випадаючого списку тощо ...


0

Делегат - це те, на що делегується завдання. Основна мета делегування - декупаж коду та забезпечення більшої гнучкості та повторного використання.

У програмуванні та конкретно об'єктно-орієнтованому програмуванні це означає, що коли метод викликається виконати якусь роботу, він передає роботу методу іншого об'єкта, на який він має посилання. Посилання може вказувати на будь-який об'єкт, який ми бажаємо, доки об'єкт відповідає заздалегідь визначеному набору методів. Ми називаємо це "програмуванням на інтерфейс" (проти програмування до конкретної реалізації класу). Інтерфейс - це загальний шаблон і не має реалізації; це просто означає рецепт, набір методів, передумов і постумов (правил).

Простий приклад:

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

Тепер ви бачите, що я можу використовувати будь-яку реалізацію, яку я хочу будь-коли, не змінюючи код у SomeCaller, оскільки тип, який doIt()передається, не є конкретним, а досить абстрактним, оскільки це інтерфейс. У світі Java це часто виражається в парадигмі сервісу, де ви викликаєте службу (об'єкт, що рекламує себе як послугу через певний інтерфейс), а потім служба закликає делегатів, щоб допомогти їй виконати свою роботу. Методи сервісу називаються грубозернистими завданнями (makePayment (), createNewUser () тощо), тоді як внутрішньо це робить багато, якщо за допомогою делегування працює азотно-зернистий, при цьому типи делегатів є інтерфейсами замість конкретних реалізацій.

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

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

(Примітка: як призначається реалізація, виходить за межі цього потоку. Перегляньте інверсію контролю та введення залежності.)


-2

Хоча насправді не є "покажчиком функції", делегат може виглядати так, що це динамічна мова, як PHP:



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

function foo() {
    print 'foo';
}

або в JavaScript ви можете зробити щось на кшталт:


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


2
Це не приклад делегування. У вашому прикладі ви використовуєте те, що називається функцією змінної, яка в основному шукає функцію, що має те саме ім'я, що і рядок, до якої відноситься змінна. Дивіться функції змінних: php.net/manual/en/functions.variable-functions.php
Aquarelle
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.