Использование делегатов в C# (или другие языки)

Позволяет говорят, что Ваш массив букв похож на это: "ABCDEFGH". У Вас есть три индекса (я, j, k) указание, которое обозначает буквами Вас, собираются использовать для текущего слова, Вы запускаете с:

A B C D E F G H
^ ^ ^
i j k

Первый Вы варьируетесь k, таким образом, следующий шаг похож на это:

A B C D E F G H
^ ^   ^
i j   k

при достижении конца Вы продолжаете и варьируетесь j и затем k снова.

A B C D E F G H
^   ^ ^
i   j k

A B C D E F G H
^   ^   ^
i   j   k

Однажды Вы j достигнутый G Вы начинаете также варьироваться я.

A B C D E F G H
  ^ ^ ^
  i j k

A B C D E F G H
  ^ ^   ^
  i j   k
...

Записанный в коде этот взгляд что-то как этот

void print_combinations(const char *string)
{
    int i, j, k;
    int len = strlen(string);

    for (i = 0; i < len - 2; i++)
    {
        for (j = i + 1; j < len - 1; j++)
        {
            for (k = j + 1; k < len; k++)
                printf("%c%c%c\n", string[i], string[j], string[k]);
        }
    }
}
7
задан Lars Truijens 6 July 2009 в 08:15
поделиться

11 ответов

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

Все это происходит автоматически за кулисами в коде, сгенерированном самой Visual Studio, поэтому вы можете не увидеть, где это происходит.

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

5
ответ дан 6 December 2019 в 06:50
поделиться

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

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

Возьмем, к примеру, все методы расширения IEnumerable, используемые LINQ.

5
ответ дан 6 December 2019 в 06:50
поделиться

Лямбда-выражения
Делегаты в основном использовались вместе с событиями. Но динамические языки показали их гораздо более широкое применение. Вот почему делегаты использовались недостаточно до C # 3.0, когда мы получили лямбда-выражения . Очень легко что-то сделать, используя лямбда-выражения (которые генерируют метод делегата)

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

4
ответ дан 6 December 2019 в 06:50
поделиться

Я попытаюсь перечислить несколько примеров, выходящих за рамки простого сценария if-else:

  1. Реализация обратных вызовов. Например, вы анализируете XML-документ и хотите, чтобы при обнаружении определенного узла вызывалась определенная функция. Вы можете передать делегатов функциям.

  2. Реализация шаблона разработки стратегии. Назначьте делегата на реализацию требуемого алгоритма / стратегии.

  3. Анонимные делегаты в случае, если вы хотите, чтобы некоторые функции выполнялись в отдельном потоке (и эта функция не имеет ничего для отправки обратно в основную программу).

  4. Подписка на события, предложенная другими.

3
ответ дан 6 December 2019 в 06:50
поделиться

В вашем примере вам понравились То же самое, поэтому вам действительно нужен массив строк.

Если вам нравится использовать делегаты в шаблоне Command, представьте, что у вас есть:

public static void ShakeHands()
{ ... }

public static void HowAreYou()
{ ... }

public static void FrenchKissing()
{ ... }

Вы можете заменить метод той же сигнатурой, но другими действиями. Вы выбрали слишком простой пример, я бы посоветовал вам найти книгу «Подробно о C #».

2
ответ дан 6 December 2019 в 06:50
поделиться

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

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

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

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

Следует отметить, что делегаты в C # в значительной степени вытеснены лямбдами, потому что компилятор может просто рассматривать его как менее подробный делегат, если он хочет, но также может передавать через выражение , которое лямбда представляет функции, в которую он передается, чтобы разрешить (часто сложную) реструктуризацию или перенацеливание желание в какой-то другой домен, например, запросы к базе данных через Linq-to-Sql.

Основное преимущество. Модель делегата net над указателями функций в стиле c состоит в том, что они фактически являются кортежем (двумя частями данных), вызываемой функцией и необязательным объектом, для которого функция должна быть вызвана. Это позволяет передавать функции с состоянием , которое является еще более мощным. Поскольку компилятор может использовать это для создания классов за вашей спиной (1), создайте новый экземпляр этого класса и поместите в него локальные переменные, таким образом разрешив замыкания .

(1) это не иметь , чтобы всегда делать это, но пока это деталь реализации

3
ответ дан 6 December 2019 в 06:50
поделиться

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

private delegate T AppServerDelegate<T>();

private T processAppServerRequest<T>(AppServerDelegate<T> delegate_) {
           try{
              return delegate_();
           }
           catch{
              //Do a bunch of standard error handling here which will be 
              //the same for all appserver  calls.
           }

        }

//Wrapped public call to AppServer
public int PostXYZRequest(string requestData1, string requestData2, 
   int pid, DateTime latestRequestTime){
           processAppServerRequest<int>(
              delegate {
                 return _appSvr.PostXYZRequest(
                    requestData1, 
                    requestData2, 
                    pid, 
                    latestRequestTime);  
              });

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

2
ответ дан 6 December 2019 в 06:50
поделиться

Делегаты используются для «вызова» кода в других классах (которые не обязательно могут быть в том же классе, или .cs, или даже той же сборке).

В вашем примере делегаты можно просто заменить операторами if, как вы указали.

Однако делегаты - это указатели на функции, которые «живут» где-то в коде, к которым, например, по организационным причинам, у вас нет доступа (легко).

1
ответ дан 6 December 2019 в 06:50
поделиться

Делегаты и связанный с ними синтаксический сахар значительно изменили мир C # (2.0+) Делегаты - это типобезопасные указатели на функции, поэтому вы используете делегатов везде, где хотите вызвать / выполнить блок кода в будущем .

Общие разделы, которые я могу вспомнить

Обратные вызовы / Событие обработчики : сделайте это, когда произойдет EventX. Или сделайте это, когда будете готовы с результатами моего вызова асинхронного метода.

myButton.Click += delegate { Console.WriteLine("Robbery in progress. Call the cops!"); }

LINQ : выбор, проекция и т. Д. Элементов, где вы хотите что-то сделать с каждым элементом перед его передачей по конвейеру. например, выберите все четные числа, затем верните квадрат каждого из них

var list = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
                 .Where(delegate(int x) { return ((x % 2) == 0); })
                 .Select(delegate(int x) { return x * x; });    
// results in 4, 16, 36, 64, 100
1
ответ дан 6 December 2019 в 06:50
поделиться

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

0
ответ дан 6 December 2019 в 06:50
поделиться

В .NET делегаты также необходимы при обновлении пользовательского интерфейса из фонового потока. Поскольку вы не можете обновить элементы управления из потока, отличного от того, который создал элементы управления, вам необходимо вызвать код обновления в контексте создаваемого потока (в основном, используя this.Invoke).

0
ответ дан 6 December 2019 в 06:50
поделиться
Другие вопросы по тегам:

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