Кто-то может дистиллировать на надлежащий английский язык, каков делегат?

Кто-то может сломать то, что делегат в простое, короткое и краткое объяснение, которое охватывает и цель и общие преимущества? Я попытался перенести голову вокруг этого, и она просто не впитывается.

17
задан Betamoo 2 June 2010 в 18:11
поделиться

11 ответов

Проще говоря, это, по сути, указатель на метод.

У вас может быть переменная, которая содержит тип делегата (так же, как у вас есть переменная int, которая может содержать тип int). Можно выполнить метод, на который указывает делегат, просто вызвав переменную как функцию.

Это позволяет вам иметь переменные функции так же, как у вас могут быть переменные данные. Ваш объект может принимать делегатов от других объектов и вызывать их,без необходимости определять все возможные функции самостоятельно.

Это очень удобно, когда вы хотите, чтобы объект делал что-то на основе заданных пользователем критериев. Например, фильтрация списка на основе определяемого пользователем выражения true/false. Можно разрешить пользователю указать функцию делегирования для использования в качестве фильтра для оценки каждого элемента списка.

21
ответ дан 30 November 2019 в 10:13
поделиться

В самых общих чертах делегат - это просто переменная, которая содержит (ссылку на) функцию. Делегаты полезны, потому что они позволяют вам передавать функцию как переменную, не беспокоясь о том, «откуда» эта функция на самом деле взялась.

Конечно, важно отметить, что функция не копируется, когда она объединяется в переменную; это просто ссылка. Например:

class Foo
{
    public string Bar
    {
        get;
        set;
    }

    public void Baz()
    {
        Console.WriteLine(Bar);
    }
}

Foo foo = new Foo();
Action someDelegate = foo.Baz;

// Produces "Hello, world".
foo.Bar = "Hello, world";
someDelegate();
1
ответ дан 30 November 2019 в 10:13
поделиться

Проще говоря, ответственность за выполнение метода делегируется другому объекту. Допустим, президент какой-то страны умирает, и президент США должен присутствовать на похоронах с посланием соболезнования. Если президент США не может поехать, он делегирует эту ответственность кому-либо - вице-президенту или госсекретарю.

То же самое и в коде. Делегат - это тип, это объект, который может выполнять метод.

например.

Class Person
{
   public string GetPersonName(Person person)
   {
     return person.FirstName + person.LastName;
   }

   //Calling the method without the use of delegate
   public void PrintName()
   {
      Console.WriteLine(GetPersonName(this));
   }

   //using delegate
   //Declare delegate which matches the methods signature
   public delegate string personNameDelegate(Person person);

  public void PrintNameUsingDelegate()
  {
      //instantiate
      personNameDelegate = new personNameDelegate(GetPersonName);

      //invoke
      personNameDelegate(this);
  }

}

Метод GetPersonName вызывается с использованием объекта делегата personNameDelegate. В качестве альтернативы мы можем использовать метод PrintNameUsingDelegate для приема делегата в качестве параметра.

public void PrintNameUsingDelegate(personNameDelegate pnd, Person person)
{
   pnd(person);
}

Преимущество состоит в том, что если кто-то хочет напечатать имя как lastname_firstname, ему / ей просто нужно обернуть этот метод в personNameDelegate и перейти к этой функции. Никаких дополнительных изменений кода не требуется.

Делегаты особенно важны в

  1. Событиях
  2. Асинхронных вызовах
  3. LINQ (как лямбда-выражения)
1
ответ дан 30 November 2019 в 10:13
поделиться

Делегат - это указатель на метод. Затем вы можете использовать делегат в качестве параметра других методов.

здесь ссылка на простой учебник.

У меня возник вопрос: "Так зачем мне это нужно?". Вы не сможете по-настоящему "понять" это, пока не решите с их помощью задачу по программированию.

3
ответ дан 30 November 2019 в 10:13
поделиться

Интересно, что никто не упомянул об одном из ключевых преимуществ делегирования - оно предпочтительнее подкласса, когда вы понимаете, что наследование - это не волшебная палочка и обычно создает больше проблем, чем решает. Это основа многих шаблонов проектирования, в первую очередь шаблона стратегии .

3
ответ дан 30 November 2019 в 10:13
поделиться

Если вы собираетесь передать задачу кому-то, делегатом будет человек, который получит работу.

В программировании это ссылка на блок кода, который действительно знает, как что-то делать. Часто это указатель на функцию или метод, который будет обрабатывать какой-либо элемент.

0
ответ дан 30 November 2019 в 10:13
поделиться

Экземпляр делегата — это ссылка на метод. Причина, по которой они полезны, заключается в том, что можно создать делегат, привязанный к определенному методу в определенном экземпляре типа. Экземпляр делегата позволяет вызывать этот метод в данном конкретном экземпляре, даже если объект, для которого будет вызываться метод, покинул лексическую область.

Наиболее распространенным использованием таких экземпляров делегатов является поддержка концепции обратных вызовов на уровне языка.

2
ответ дан 30 November 2019 в 10:13
поделиться

Он просто ссылается на метод. Они отлично используются при работе с перекрестной резьбой.

Вот пример прямо из моего кода.

 //Start our advertisiment thread
    rotator = new Thread(initRotate);
    rotator.Priority = ThreadPriority.Lowest;
    rotator.Start();

    #region Ad Rotation
    private delegate void ad();
    private void initRotate()
    {
        ad ad = new ad(adHelper);
        while (true)
        {
            this.Invoke(ad);
            Thread.Sleep(30000);
        }

    }

    private void adHelper()
    {
        List<string> tmp = Lobby.AdRotator.RotateAd();
        picBanner.ImageLocation = @tmp[0].ToString();
        picBanner.Tag = tmp[1].ToString();            
    }
    #endregion

Если вы не используете делегат, вы не сможете перекрестно перейти и вызвать функцию Lobby.AdRotator.

2
ответ дан 30 November 2019 в 10:13
поделиться

У меня есть функция:

public long GiveMeTwoTimesTwo()
{
    return 2 * 2;
}

Отстойная функция. Что, если я хочу 3 * 3?

public long GiveMeThreeTimesThree()
{
    return 3 * 3;
}

Слишком много текста. Я ленивый!

public long SquareOf(int n)
{
    return n * n;
}

Моей функции SquareOf все равно, что такое n . Он будет работать правильно для любого переданного номера n . Он не знает точно, что такое номер n , но знает , что n ] является целым числом. Вы не можете передать «Ха-ха, не целое число» в SquareOf .

Вот еще одна функция:

public void DoSomethingRad()
{
    int x = 4;
    long y = SquareOf(x);
    Console.WriteLine(y);
}

Вопреки своему названию, DoSomethingRad на самом деле ничего не делает. Тем не менее, он записывает SquareOf (4), который равен 16. Можем ли мы изменить его, чтобы он был менее утомительным?

public void DoSomethingRad(int numberToSquare)
{
    long y = SquareOf(numberToSquare);
    Console.WriteLine(y);
}

DoSomethingRad явно все еще довольно неудачный. Но, по крайней мере, теперь мы можем передать число в квадрат, чтобы оно не записывало 16 каждый раз. (Он напишет 1, или 4, или 9, или 16, или ... zzzz все еще скучно).

Было бы хорошо, если бы существовал способ изменить то, что происходит с переданным числом. Возможно, мы не хотим возводить его в квадрат; может быть, мы хотим кубить его или вычесть из 69 (число выбрано наугад из моей головы).

При дальнейшем рассмотрении кажется, что единственная часть SquareOf , о которой заботится DoSomethingRad , - это то, что мы можем дать ему целое число ( numberToSquare ) и что он дает нам long (потому что мы помещаем его возвращаемое значение в y , а y - это long ).

public long CubeOf(int n)
{
    return n * n * n;
}

public void DoSomethingLeet(int numberToSquare)
{
    long y = CubeOf(numberToSquare);
    Console.WriteLine(y);
}

Видите, насколько DoSomethingLeet похож на DoSomethingRad ? Если бы только был способ передать поведение ( DoX () ) вместо просто данных ( int n ) ...

Итак, теперь, если мы хотим написать квадрат числа, мы можем DoSomethingRad , а если мы хотим написать куб числа, мы можем DoSomethingLeet . Итак, если мы хотим записать число, вычитаемое из 69, нужно ли создавать другой метод, DoSomethingCool ? Нет, потому что для этого требуется слишком много набора текста (и, что более важно, это мешает нам изменить интересное поведение, изменив только один аспект нашей программы).

Итак, мы получаем:

public long Radlicious(int doSomethingToMe, Func<int, long> doSomething)
{
    long y = doSomething(doSomethingToMe);
    Console.WriteLine(y);
}

Мы можем вызвать этот метод, написав следующее:

Radlicious(77, SquareOf);

Func - это особый вид делегата. Он хранит поведение, которое принимает целые числа и выводит длинных сек. Мы не уверены, что метод, на который он указывает, будет делать с любым заданным целым числом, которое мы передаем; все, что мы знаем, это то, что, что бы ни случилось, мы вернем длинную .

Нам не нужно указывать какие-либо параметры для SquareOf , потому что Func описывает поведение , а не данные. Вызов Radlicious (77, SquareOf) просто дает Radlicious общее поведение SquareOf («Я беру число и возвращаю его квадрат»), а не то, что SquareOf будет do с любым целым числом .

Итак, если вы поняли, о чем я говорю, то вы уже превзошли меня, потому что я сам действительно не понимаю этого.

* ЗАКОНЧИТЬ ОТВЕТ, НАЧАТЬ ИДИОЦИЮ НАЧИНАЕТСЯ *

Я имею в виду, похоже, что int s может быть воспринято как действительно скучное поведение:

static int Nine()
{
    return 9;
}

Тем не менее, грань между тем, что является данными, и поведение кажется размытым, а то, что обычно воспринимается как данные, просто скучное поведение.

Конечно, можно представить супер "интересное" поведение, которое принимает всевозможные абстрактные параметры, но требует тонны информации, чтобы иметь возможность его вызвать. Что, если бы нам потребовалось предоставить исходный код, который он будет компилировать и запускать для нас?

Что ж, тогда наша абстракция, похоже, вернула нас обратно к исходной точке. У нас настолько абстрактное поведение, что требуется весь исходный код нашей программы, чтобы определить, что она собирается делать. Это полностью неопределенное поведение: функция может делать что угодно , но ей нужно предоставить все , чтобы определять, что она делает. С другой стороны, полностью определенное поведение, такое как Nine () , не требует никакой дополнительной информации, но не может делать ничего, кроме return 9 .

И что? Я не знаю.

30
ответ дан 30 November 2019 в 10:13
поделиться

Как говорили другие, делегат — это ссылка на функцию. Одним из наиболее полезных применений (IMO) является события. При регистрации события регистрируется функция для вызова события, а делегаты идеально подходят для этой задачи.

1
ответ дан 30 November 2019 в 10:13
поделиться

В самых простых терминах, которые я могу придумать, это: делегат перекладывает бремя работы в руки класса, который в значительной степени знает что делать. Думайте об этом как о ребенке, который не хочет вырасти, чтобы полностью походить на своего старшего брата, но все еще нуждается в его руководстве и указаниях. Вместо того, чтобы унаследовать все методы от своего брата (т.е. создать подклассы), он просто заставляет своего брата выполнять работу или Младший брат делает что-то, что требует действий от старшего брата. Когда вы попадаете в ряды протоколов, старший брат определяет, что абсолютно необходимо, или он может дать вам гибкость в выборе того, что вы хотите заставить его делать в определенных событиях (например, неформальные и формальные протоколы, как указано в цели-C).

Абсолютное преимущество этой концепции в том, что вам не нужно создавать подкласс. Если вы хотите, чтобы что-то попало в очередь, выполняйте приказы, когда происходит событие, делегат позволяет развитому классу держать его за руку и отдавать приказы, если это необходимо.

0
ответ дан 30 November 2019 в 10:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: