Каково ваше использование делегатов в С#?
Когда вы будете использовать делегатов в С#?
Ответ 1
Теперь, когда в С# есть лямбда-выражения и анонимные методы, я использую делегаты гораздо больше. В С# 1, где вам всегда приходилось иметь отдельный метод реализации логики, использование делегата часто не имело смысла. В эти дни я использую делегатов для:
- Обработчики событий (для GUI и т.д.)
- Начальные темы
- Обратные вызовы (например, для асинхронных API)
- LINQ и аналогичные (List.Find и т.д.)
- В любом другом месте, где я хочу эффективно применять код "шаблон" с некоторой специализированной логикой внутри (где делегат предоставляет специализацию)
Ответ 2
Делегаты очень полезны для многих целей.
Одна из таких целей - использовать их для фильтрации последовательностей данных. В этом случае вы должны использовать предикат-делегат, который принимает один аргумент и возвращает true или false в зависимости от реализации самого делегата.
Вот глупый пример - я уверен, что вы можете экстраполировать что-то более полезное из этого:
using System;
using System.Linq;
using System.Collections.Generic;
class Program
{
static void Main()
{
List<String> names = new List<String>
{
"Nicole Hare",
"Michael Hare",
"Joe Hare",
"Sammy Hare",
"George Washington",
};
// Here I am passing "inMyFamily" to the "Where" extension method
// on my List<String>. The C# compiler automatically creates
// a delegate instance for me.
IEnumerable<String> myFamily = names.Where(inMyFamily);
foreach (String name in myFamily)
Console.WriteLine(name);
}
static Boolean inMyFamily(String name)
{
return name.EndsWith("Hare");
}
}
Ответ 3
Нашел еще один интересный ответ:
Сотрудник просто задал мне этот вопрос - какой смысл делегатов в .NET? Мой ответ был очень коротким и один, который он не нашел в Интернете: отложить выполнение метода.
Источник: LosTechies
Точно так же, как LINQ.
Ответ 4
Вы можете использовать делегаты для объявления переменных и параметров, типизированных для функции.
Пример
Рассмотрим шаблон "заимствования ресурсов". Вы хотите контролировать создание и очистку ресурса, позволяя клиентскому коду "заимствовать" ресурс между ними.
Объявляет тип делегата.
public delegate void DataReaderUser( System.Data.IDataReader dataReader );
Любой метод, соответствующий этой сигнатуре, может использоваться для создания экземпляра этого делегата. В С# 2.0 это можно сделать неявно, просто используя имя метода, а также используя анонимные методы.
Этот метод использует этот тип как параметр. Обратите внимание на вызов делегата.
public class DataProvider
{
protected string _connectionString;
public DataProvider( string psConnectionString )
{
_connectionString = psConnectionString;
}
public void UseReader( string psSELECT, DataReaderUser readerUser )
{
using ( SqlConnection connection = new SqlConnection( _connectionString ) )
try
{
SqlCommand command = new SqlCommand( psSELECT, connection );
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while ( reader.Read() )
readerUser( reader ); // the delegate is invoked
}
catch ( System.Exception ex )
{
// handle exception
throw ex;
}
}
}
Функция может быть вызвана с анонимным методом следующим образом. Обратите внимание, что анонимный метод может использовать переменные, объявленные вне себя. Это очень удобно (хотя пример немного надуманный).
string sTableName = "test";
string sQuery = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='" + sTableName + "'";
DataProvider.UseReader( sQuery,
delegate( System.Data.IDataReader reader )
{
Console.WriteLine( sTableName + "." + reader[0] );
} );
Ответ 5
Делегаты часто могут использоваться вместо интерфейса с одним методом, общим примером этого может служить шаблон наблюдателя. На других языках, если вы хотите получить уведомление о том, что что-то произошло, вы можете определить что-то вроде:
class IObserver{ void Notify(...); }
В С# это чаще выражается с помощью событий, где обработчик является делегатом, например:
myObject.SomeEvent += delegate{ Console.WriteLine("..."); };
Еще одно замечательное место для использования делегатов, если вам нужно передать предикат в функцию, например, при выборе набора элементов из списка:
myList.Where(i => i > 10);
Вышеприведенный пример синтаксиса лямбда, который также может быть записан следующим образом:
myList.Where(delegate(int i){ return i > 10; });
Другим местом, где полезно использовать делегаты, является регистрация функций factory, например:
myFactory.RegisterFactory(Widgets.Foo, () => new FooWidget());
var widget = myFactory.BuildWidget(Widgets.Foo);
Надеюсь, это поможет!
Ответ 6
Я прихожу к этому очень поздно, но у меня возникли проблемы с выяснением цели делегатов сегодня и написаны две простые программы, которые дают тот же результат, который, как мне кажется, хорошо объясняет их цель.
NoDelegates.cs
using System;
public class Test {
public const int MAX_VALUE = 255;
public const int MIN_VALUE = 10;
public static void checkInt(int a) {
Console.Write("checkInt result of {0}: ", a);
if (a < MAX_VALUE && a > MIN_VALUE)
Console.WriteLine("max and min value is valid");
else
Console.WriteLine("max and min value is not valid");
}
public static void checkMax(int a) {
Console.Write("checkMax result of {0}: ", a);
if (a < MAX_VALUE)
Console.WriteLine("max value is valid");
else
Console.WriteLine("max value is not valid");
}
public static void checkMin(int a) {
Console.Write("checkMin result of {0}: ", a);
if (a > MIN_VALUE)
Console.WriteLine("min value is valid");
else
Console.WriteLine("min value is not valid");
Console.WriteLine("");
}
}
public class Driver {
public static void Main(string [] args) {
Test.checkInt(1);
Test.checkMax(1);
Test.checkMin(1);
Test.checkInt(10);
Test.checkMax(10);
Test.checkMin(10);
Test.checkInt(20);
Test.checkMax(20);
Test.checkMin(20);
Test.checkInt(30);
Test.checkMax(30);
Test.checkMin(30);
Test.checkInt(254);
Test.checkMax(254);
Test.checkMin(254);
Test.checkInt(255);
Test.checkMax(255);
Test.checkMin(255);
Test.checkInt(256);
Test.checkMax(256);
Test.checkMin(256);
}
}
Delegates.cs
using System;
public delegate void Valid(int a);
public class Test {
public const int MAX_VALUE = 255;
public const int MIN_VALUE = 10;
public static void checkInt(int a) {
Console.Write("checkInt result of {0}: ", a);
if (a < MAX_VALUE && a > MIN_VALUE)
Console.WriteLine("max and min value is valid");
else
Console.WriteLine("max and min value is not valid");
}
public static void checkMax(int a) {
Console.Write("checkMax result of {0}: ", a);
if (a < MAX_VALUE)
Console.WriteLine("max value is valid");
else
Console.WriteLine("max value is not valid");
}
public static void checkMin(int a) {
Console.Write("checkMin result of {0}: ", a);
if (a > MIN_VALUE)
Console.WriteLine("min value is valid");
else
Console.WriteLine("min value is not valid");
Console.WriteLine("");
}
}
public class Driver {
public static void Main(string [] args) {
Valid v1 = new Valid(Test.checkInt);
v1 += new Valid(Test.checkMax);
v1 += new Valid(Test.checkMin);
v1(1);
v1(10);
v1(20);
v1(30);
v1(254);
v1(255);
v1(256);
}
}
Ответ 7
Несколько другое использование - ускорить отражение; т.е. вместо использования отражения каждый раз, вы можете использовать Delegate.CreateDelegate
для создания (типизированного) делегирования метода (a MethodInfo
) и вместо этого вызвать делегата. Это намного быстрее для каждого звонка, поскольку проверки уже выполнены.
С помощью Expression
вы также можете сделать то же самое, чтобы создать код "на лету" - например, вы можете легко создать Expression
, который представляет оператор + для типа, выбранного во время выполнения (чтобы обеспечить поддержку оператора для генерических средств, которые язык не предоставляет); и вы можете скомпилировать Expression
для типизированного делегата - сделанное задание.
Ответ 8
Делегаты используются при каждом использовании событий - в том, что механизм их работы.
Кроме того, делегаты очень полезны для таких вещей, как использование запросов LINQ. Например, многие запросы LINQ принимают делегат (часто Func<T,TResult>
), который можно использовать для фильтрации.
Ответ 9
подписывание обработчиков событий на события
Ответ 10
Пример может выглядеть как здесь. У вас есть метод обработки объекта, который отвечает определенным требованиям. Однако вы хотите иметь возможность обрабатывать объект несколькими способами. Вместо того, чтобы создавать отдельные методы, вы можете просто назначить метод сопоставления, который обрабатывает объект для делегата, и передать делегат методу, который выбирает объекты. Таким образом, вы можете назначить разные методы для одного метода выбора. Я попытался сделать это понятным.
Ответ 11
Я использую делегаты для связи с потоками.
Например, у меня может быть приложение win forms, которое загружает файл. Приложение запускает рабочий поток для загрузки (что предотвращает блокировку GUI). Рабочий поток использует делегаты для отправки сообщений о статусе (например, загрузки) обратно в основную программу, так что графический интерфейс пользователя может обновлять строку состояния.
Ответ 12
-
Для обработчика событий
-
Пропустить метод в параметрах метода
Ответ 13
Первая строка используется для замены шаблона Observer/Observable (events). Вторая, красивая элегантная версия шаблона стратегии. Различные другие обычаи могут быть собраны, хотя и более эзотеричны, чем эти первые два, я думаю.
Ответ 14
События, другие операции anynch
Ответ 15
Каждый раз, когда вы хотите инкапсулировать поведение, но вызывайте его единообразным способом. Обработчики событий, функции обратного вызова и т.д. Вы можете выполнять аналогичные действия с использованием интерфейсов и приведений, но иногда поведение не обязательно связано с типом или объектом. Иногда у вас просто есть поведение, которое вам нужно инкапсулировать.
Ответ 16
Инициализация ленивых параметров! Помимо всех предыдущих ответов (шаблон стратегии, шаблон наблюдателя и т.д.), Делегаты позволяют обрабатывать ленивую инициализацию параметров. Например, предположим, что у вас есть функция Download(), которая занимает довольно много времени и возвращает определенный DownloadedObject. Этот объект потребляется хранилищем в зависимости от определенных Условий. Как правило, вы бы:
storage.Store(conditions, Download(item))
Однако, с делегатами (точнее, лямбдами) вы можете сделать следующее, изменив подпись хранилища, чтобы он получил условие и объект Func < Item, DownloadedObject > и используйте его следующим образом:
storage.Store(conditions, (item) => Download(item))
Поэтому хранилище будет оценивать делегат только при необходимости, выполняя загрузку в зависимости от условий.
Ответ 17
Использование делегатов
- Обработка событий
- Multi Casting
Ответ 18
Параметр сравнения в массиве In Array.Sort(T [], сравнение сравнения), List.Sort(сравнение сравнения) и т.д.
Ответ 19
Насколько я знаю, делегаты могут быть преобразованы в указатели на функции. Это облегчает жизнь, когда взаимодействует с собственным кодом, который использует указатели на функции, поскольку они могут эффективно быть объектно ориентированными, хотя исходный программист не сделал никаких условий для этого.
Ответ 20
Делегат используется для вызова метода по его ссылке. Например:
delegate void del_(int no1,int no2);
class Math
{
public static void add(int x,int y)
{
Console.WriteLine(x+y);
}
public static void sub(int x,int y)
{
Console.WriteLine(x-y);
}
}
class Program
{
static void Main(string[] args)
{
del_ d1 = new del_(Math.add);
d1(10, 20);
del_ d2 = new del_(Math.sub);
d2(20, 10);
Console.ReadKey();
}
}