Подтвердить что ты не робот

Делегат 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);
}

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

4b9b3361

Ответ 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.