Функциональный делегат против функции - PullRequest
12 голосов
/ 24 июня 2010

Может ли кто-нибудь рассказать мне о преимуществах использования делегата по сравнению с вызовом самой функции, как показано ниже (или, другими словами, почему стоит выбрать вариант A вместо варианта B)?Вчера вечером я просматривал чей-то код linq, и у него было что-то похожее на вариант А. Но он использовался для возврата скомпилированного запроса 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);
    }        
}

************ РЕДАКТИРОВАТЬ ************

Не уверен, что это лучше объясняет мой вопрос, ноВот пример типа кода, который изначально заставил меня задуматься об этом:

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

Есть ли какое-либо преимущество при написании такой функции?

Ответы [ 6 ]

13 голосов
/ 24 июня 2010

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

Однако у делегатов много применений.«Передача» другим методам является основным использованием, хотя хранение функции и ее использование позже также очень полезно.

LINQ полностью построен на основе этой концепции.Когда вы делаете:

var results = myCollection.Where(item => item == "Foo");

Вы передаете делегат (определенный как лямбда: item => item == "Foo") функции Where в библиотеках LINQ.Это то, что заставляет его работать правильно.

4 голосов
/ 26 июня 2010

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

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

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

3 голосов
/ 24 июня 2010

Это полезно, только если вам нужно передать делегата. Если вы можете разрешить функцию во время компиляции, это менее полезно.

2 голосов
/ 24 июня 2010

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

1 голос
/ 29 июня 2013
// 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);
}

В приведенном выше случае вариант B - это то, с чем я бы согласился, если только мне не нужно изменить функциональность SayTwoWords. В случае варианта A, SayTwoWords может быть назначена другая функция. Поймайте более подробные различия в этом ответе :

В ситуации, когда вариант А имеет смысл. Рассмотрим случай, когда вам нужно скомпилировать выражение для делегата. Так как компиляция выражений тяжелая, вы захотите сделать это только один раз. Такой шаблон помогает:

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 выполняется только один раз, где, как и во втором случае, (101) * будет вызываться каждый раз (дорогой) Get.

1 голос
/ 24 июня 2010

вы можете использовать делегаты как «указатели на функции», так что вы можете передавать функции или «действия» другим функциям для выполнения.

Что также было бы интересно для делегатов, так это возможность «прекомпилировать», как вы «строите» новую функцию, а затем возвращаете эту функцию в ваше приложение

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...