Почему я могу использовать лямбда-выражение вместо делегата обратного вызова? - PullRequest
8 голосов
/ 20 декабря 2010

Я обнаружил новый синтаксис C # и не понимаю, что это значит.Вот код, связанный с синтаксисом:

1)

BeginInvoke(new Action(() =>
    {
        PopulateUI(ds);
    }));

2)

private void OnFormLoad() 
{ 
    ThreadPool.QueueUserWorkItem(() => GetSqlData()); 
}

Что означает new Action() и что означаетсимвол =>?

Синтаксис ThreadPool.QueueUserWorkItem был ThreadPool.QueueUserWorkItem(new WaitCallback(PrintOut), "Hello");, но здесь он показывает ThreadPool.QueueUserWorkItem(() => GetSqlData());, так как он работает?Почему WaitCallback отсутствует?Пожалуйста, объясните подробно.

Большое спасибо.

Ответы [ 4 ]

6 голосов
/ 20 декабря 2010

Посмотрите на

Делегат действия

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

и

и Лямбда-выражения (Руководство по программированию в C #)

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

Все лямбда-выражения используют лямбда-оператор =>, который читается как «идет».Левая часть лямбда-оператора указывает входные параметры (если есть), а правая часть содержит блок выражений или операторов.Лямбда-выражение x => x * x читается как «x соответствует x раз x».

5 голосов
/ 20 декабря 2010

Как уже говорили другие, это лямбда, которая в основном является анонимной (неназванной) локальной функцией.

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

// With a lambda
private void OnFormLoad()
{
    ThreadPool.QueueUserWorkItem(() => GetSqlData()); 
}

// Without a lambda
private void OnFormLoad() 
{ 
    ThreadPool.QueueUserWorkItem(ExecuteGetSqlData);
}

private void ExecuteGetSqlData()
{
    // If GetSqlData returns something, change this to "return GetSqlData();"
    GetSqlData();
}

Что касается другого кода, обычно вам не нужно делать new Action.Проблема заключается в том, что метод BeginInvoke принимает Delegate, что является чем-то вроде старой школы, и нарушает работу большинства новых кодов.

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

Также обратите внимание, что если вы видите что-то вроде: (Action) (() => Blah()), это в значительной степени совпадает с new Action(() => Blah()).

4 голосов
/ 20 декабря 2010

Они известны как лямбда-выражения , которые не очень отличаются от делегатов в C #.

Пустое () означает, что аргументов нет, и что находится между (необязательно)) {} - это тела лямбда-выражения.Оператор => просто связывает оба выражения вместе, чтобы создать лямбда-выражение.Кроме того, они обычно встречаются в коде LINQ.

В new Action() нет ничего особенного, только то, что это делегат , который может сопоставить лямбда-выражение с собой.

Что касается ThreadPool.QueueUserWorkItem(), аргумент WaitCallback является делегатом.Вы можете передать имя именованного делегата в качестве аргумента, передать анонимный объект delegate или написать лямбда-выражение для этого анонимного delegate (в вашем случае это () => GetSqlData()).

2 голосов
/ 20 декабря 2010
...