Может ли кто-то перевести на правильный английский, что такое делегат?

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

Ответы

Ответ 1

В простейших возможных терминах это по существу указатель на метод.

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

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

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

Ответ 2

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

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 является целым числом. Вы не можете передать "Haha not an integer" в 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<int, long> - особый вид делегата. Он хранит поведение, которое принимает целые числа и выплевывает long s. Мы не уверены, что метод, на который он указывает, будет делать с любым заданным целым числом, которое мы передаем; все, что мы знаем, это то, что бы ни случилось, мы получим обратно long.

Нам не нужно указывать параметры SquareOf, потому что Func<int, long> описывает поведение, а не данные. Вызов Radlicious(77, SquareOf) просто дает Radlicious общее поведение SquareOf ( "Я беру число и возвращаю его квадрат" ), а не то, что SquareOf будет делать с любым конкретным целым числом.

Теперь, если вы поняли, о чем я говорю, тогда у вас уже есть один-вверх, потому что я сам на самом деле не получаю этого.

* END ANSWER, НАЧИНАЙТЕ СВОЙСТВАМИ ИСПЫТАНИЙ *

Я имею в виду, кажется, что int можно воспринимать как просто очень скучное поведение:

static int Nine()
{
    return 9;
}

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

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

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

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

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

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

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

Ответ 6

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

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

 //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.

Ответ 7

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

Ответ 8

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

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

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

Ответ 9

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

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

например.

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 вызывается с использованием объекта delegate personNameDelegate. Кроме того, метод PrintNameUsingDelegate может принимать делегат в качестве параметра.

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

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

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

  • События
  • Асинхронные вызовы
  • LINQ (как лямбда-выражения)

Ответ 10

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

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

Ответ 11

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

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