Делегат Func против функции
Может ли кто-нибудь сказать мне преимущества использования делегата, а не для вызова самой функции, как показано ниже (или, другими словами, зачем выбирать вариант A над вариантом B)? Я смотрел на кого-то код linq прошлой ночью, и у них было что-то похожее на вариант A, но оно использовалось для возврата скомпилированного запроса linq.
Я понимаю, что первая теперь может быть передана другим функциям.. просто не уверен в ее практичности. Кстати, я понимаю, что это не будет компилироваться как есть.. раскомментировала одну из функций перед публикацией. TYIA
class Program
{
static void Main(string[] args)
{
Console.WriteLine(SayTwoWords("Hello", "World"));
Console.ReadKey();
}
// Option A
private static Func<string, string, string>
SayTwoWords = (a, b) => String.Format("{0} {1}", a, b);
// Option B
private static string SayTwoWords(string a, string b)
{
return String.Format("{0} {1}", a, b);
}
}
************ ************ EDIT
Не уверен, что он лучше объясняет мой вопрос, но вот пример типа кода, который изначально заставлял меня думать об этом:
public static class clsCompiledQuery
{
public static Func<DataContext, string, IQueryable<clsCustomerEntity>>
getCustomers = CompiledQuery.Compile((DataContext db, string strCustCode)
=> from objCustomer in db.GetTable<clsCustomerEntity>()
where objCustomer.CustomerCode == strCustCode
select objCustomer);
}
Есть ли какое-либо преимущество в написании функции таким образом?
Ответы
Ответ 1
В коде, который вы опубликовали, нет никакого преимущества. В вашем коде использование делегата просто добавляет сложности, а также дополнительную стоимость исполнения - так что вам лучше просто вызвать метод напрямую.
Однако делегаты имеют много применений. "Переход" к другим методам - основное использование, хотя хранение функции и ее использование позже также очень полезно.
LINQ полностью построен над этой концепцией. Когда вы выполните:
var results = myCollection.Where(item => item == "Foo");
Вы передаете делегат (определенный как lambda: item => item == "Foo"
) в функцию Where
в библиотеках LINQ. Это то, что заставляет его работать должным образом.
Ответ 2
Очень полезная функция делегатов заключается в том, что вы можете отправлять их туда, где хотите. Это похоже на то, что ваша функция везде вам нужна. Большим преимуществом для этого является обработка событий. Скажем, у вас есть кнопка, и когда пользователь нажимает эту кнопку, вам нужно вызвать любое количество функций. Если вы думаете об этом, вы можете сделать несколько способов:
Вы могли:
Вызовите функцию, которая вызывает функцию, которую вы хотите вызвать.
Это означает, что для каждой новой функции, которую вы хотите вызвать, вы должны жестко записать ее в эту функцию. Очень раздражает.
ИЛИ
У вас может быть открытый список имен каждой функции, которую вы хотите вызвать (делегаты), и каждый может добавлять или удалять эти функции в любое время, если владелец события клика не должен знать или даже выполнять какую-либо работу в отношении любого из них, Когда происходит событие клика, каждое событие в списке вызывается и отправляется с теми же параметрами, и все готово.
Ответ 3
Это полезно, только если вам нужно передать делегата. Если вы можете решить эту функцию во время компиляции, она менее полезна.
Ответ 4
С помощью статического метода вы должны пройти все необходимые переменные.
С делегатом вы можете встроить свою реализацию и получить доступ к переменным в области.
Ответ 5
вы можете использовать делегаты как "указатели на функции", поэтому вы можете дать функции или "действия" другим функциям для выполнения.
что также было бы интересно с делегатами, это возможность "предварительной компиляции", например, "создать" новую функцию, а затем вернуть эту функцию в ваше приложение
Ответ 6
// Option A
private static Func<string, string, string>
SayTwoWords = (a, b) => String.Format("{0} {1}", a, b);
// Option B
private static string SayTwoWords(string a, string b)
{
return String.Format("{0} {1}", a, b);
}
В приведенном выше случае вариант В - это то, с чем я бы пошел, если мне не нужна функциональность SayTwoWords
, которую нужно изменить. В случае опции A SayTwoWords
может быть назначена другая функция. Поймайте более подробные отличия в этом ответе:
Существует ситуация, когда вариант A имеет смысл. Рассмотрим случай, когда вы должны скомпилировать выражение для делегата. Поскольку компиляция выражения является тяжелой, это то, что вы хотели бы сделать это только один раз. Подобный шаблон помогает:
public static class Cache<T>
{
public static readonly Func<T> Get = GetImpl();
static Func<T> GetImpl()
{
//build expression and return compiled delegate
}
}
вместо
public static class Cache<T>
{
public static T Get()
{
//build expression, compile delegate and invoke the delegate
}
}
В первом случае, когда вы вызываете Get
, GetImpl
выполняется только один раз, где, как и во втором случае, каждый раз будет вызываться (дорогой) Get
.