В чем разница между Func <string, string> и делегатом? - PullRequest
60 голосов
/ 25 июля 2011

Я вижу делегатов в двух формах:

A. Func<string, string> convertMethod = lambda 

B. public delegate string convertMethod(string value);

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

Ответы [ 4 ]

59 голосов
/ 25 июля 2011

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

public static class Program
{
    // you can define your own delegate for a nice meaningful name, but the
    // generic delegates (Func, Action, Predicate) are all defined already
    public delegate string ConvertedMethod(string value);

    public static void Main()
    {
        // both work fine for taking methods, lambdas, etc.
        Func<string, string> convertedMethod = s => s + ", Hello!";
        ConvertedMethod convertedMethod2 = s => s + ", Hello!";
    }
}

Но, более конкретно, и Func<string,string>, и delegate string convertMethod(string) будут способны содержать одни и те же определения методов, будь то методы, анонимные методы илиЛямбда-выражения.

То, что вы должны использовать, зависит от ситуации.Если вы хотите, чтобы ваш делегат больше определялся тем, что он принимает и возвращает, тогда обобщенные делегаты идеальны.Если вы хотите, чтобы у делегата было какое-то специальное имя, которое дает больше определения того, что должен делать этот делегат (помимо простого Action, Predicate и т. Д.), Тогда создание собственного делегата всегда является опцией.

12 голосов
/ 25 июля 2011

Пример кода, который у вас есть, немного сбивает с толку, поэтому позвольте мне разобраться.Следующие 2 пункта являются декларациями делегатов.Их легко обнаружить, потому что они всегда будут содержать ключевое слово delegate

public delegate TReturn Func<TArg, TReturn>(Targ value);
public delegate string convertMethod(string value);

Эта строка кода присваивает значение локальному элементу, который вводится делегату

Func<string, string> local = lambda;

Приведенный выше код не ограничивается использованием только лямбды.Значением также может быть группа совместимых методов или другое значение делегата.

Еще один момент, на который следует обратить внимание, заключается в том, что, хотя Func<string, string> и convertMethod оба являются делегатами с одинаковыми сигнатурами, их значения не могут быть преобразованы друг в друга.Например, следующее недопустимо

Func<string, string> local1 = ...;
convertMethod local2 = local1; // Error!!!
8 голосов
/ 25 июля 2011

С MSDN ,

В версиях C # до 2.0 единственным способом объявления делегата было использование именованных методов.В C # 2.0 введены анонимные методы, а в C # 3.0 и более поздних версиях лямбда-выражения заменяют анонимные методы как предпочтительный способ написания встроенного кода.который анонимный метод обеспечивает функциональность, не найденную в лямбда-выражениях.Анонимные методы позволяют вам опустить список параметров.Это означает, что анонимный метод может быть преобразован в делегатов с различными сигнатурами.

Вам также может быть интересен этот SO-ответ на ключевое слово делегата против лямбда-выражения .

Кроме того, в MSDN есть хорошая статья о лямбда-выражениях :

delegate int del(int i);
static void Main(string[] args)
{
    del myDelegate = x => x * x;
    int j = myDelegate(5); //j = 25
}

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

4 голосов
/ 25 июля 2011

A инициализирует экземпляр делегата (который может быть вызван немедленно). Это переменная типа Func .

B определяет определение делегата (его подпись). Его можно использовать для последующего определения переменных типа convertMethod .

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