2010-06-24 4 views
11

Может ли кто-нибудь сказать мне преимущества использования делегата, а не для вызова самой функции, как показано ниже (или, другими словами, зачем выбрать вариант A над вариантом B)? Вчера я смотрел чей-то код linq, и у них было что-то похожее на вариант A, но оно использовалось для возврата скомпилированного запроса linq.Func Delegate vs Function

Я понимаю, что первые могут быть переданы другим функциям .. просто не уверены в его практичности. Кстати, я понимаю, что это не будет компилироваться как есть .. раскомментировала одну из функций перед публикацией. 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); 
} 

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

+0

Возможный дубликат [я до сих пор не получаю делегатов] (http://stackoverflow.com/questions/399222/i-still-dont-get-delegates) –

ответ

13

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

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

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

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

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

3

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

+0

Вы можете делегировать любую существующую функцию в одной строке, I на самом деле не думаю, что есть преимущество, если вы не делаете его, как 10 000 раз (меньше созданных объектов). – Aren

1

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

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

2

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

4

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

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

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

1
// 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 быть изменены. В случае варианта А SayTwoWords может быть назначена другая функция. Поймать более подробные отличия in this answer:

Есть ситуация, когда вариант 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 будет каждый раз.

Смежные вопросы