Есть ли случай, когда синтаксис делегата предпочтительнее, чем лямбда-выражение для анонимных методов? - PullRequest
12 голосов
/ 20 сентября 2008

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

Любое место, где нам все еще приходится использовать делегаты и лямбда-выражения, не будет работать?

Ответы [ 7 ]

27 голосов
/ 20 сентября 2008

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

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

public static void Invoke(Delegate d)
{
  d.DynamicInvoke();
}

static void Main(string[] args)
{
  // fails
  Invoke(() => Console.WriteLine("Test"));

  // works
  Invoke(new Action(() => Console.WriteLine("Test")));

  Console.ReadKey();
}

Сбой строки кода приведет к ошибке компилятора «Невозможно преобразовать лямбда-выражение в тип« System.Delegate », так как это не тип делегата».

8 голосов
/ 20 сентября 2008

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

 delegate(int i) { Console.WriteLine(i.ToString()) }

можно заменить на

f => Console.WriteLine(f.ToString())
7 голосов
/ 29 сентября 2008

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

List<string> names = GetNames();
names.ForEach(Console.WriteLine);
  1. делает код более читабельным и, следовательно, простым для понимания.
  2. Это делает код короче, таким образом, меньше работает для нас;)

С другой стороны, злоупотреблять ими очень просто. Длинные и / или сложные лямбда-выражения имеют тенденцию быть:

  1. Трудно понять для новых разработчиков
  2. Менее объектно-ориентированный
  3. Гораздо сложнее читать

Итак, «означает ли это, что нам больше не нужно использовать делегаты или анонимные методы?» Нет - используйте лямбда-выражение, где вы выигрываете время / читаемость, в противном случае рассмотрите возможность использования делегатов.

4 голосов
/ 28 сентября 2008

Делегат имеет два значения в C #.

Ключевое слово delegate может использоваться для определения типа сигнатуры функции. Это обычно используется при определении сигнатуры функций более высокого порядка, то есть функций, которые принимают другие функции в качестве аргументов. Такое использование делегата по-прежнему актуально.

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

3 голосов
/ 20 сентября 2008

Lamda - это просто синтаксический сахар для делегатов, они не просто встроенные, вы можете делать следующее:

s.Find(a =>
{
    if (a.StartsWith("H"))
        return a.Equals("HI");
    else
        return !a.Equals("FOO");
});

И делегаты по-прежнему используются при определении событий или когда у вас много аргументов и вы хотите действительно строго набирать вызываемый метод.

3 голосов
/ 20 сентября 2008

Лямбда-выражения являются просто «синтаксическим сахаром», компилятор сгенерирует для вас соответствующие делегаты. Вы можете исследовать это, используя отражатель Лутца Редера.

2 голосов
/ 03 июля 2014

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

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

Например, вы можете сделать:

Action<int> a = delegate { }; //takes 1 argument, but not specified on the RHS

Пока это не удается:

Action<int> a = => { }; //omitted parameter, doesnt compile.

Этот метод наиболее удобен при написании обработчиков событий, например:

button.onClicked += delegate { Console.WriteLine("clicked"); };

Это не сильное преимущество. Лучше всегда использовать новый синтаксис imho.

...