Я смотрю на новые реализации в C # 7.0, и мне интересно, что они реализовали локальные функции, но я не могу представить сценарий, где локальная функция предпочтительнее лямбда-выражения, и в чем разница между ними.
Я понимаю, что лямбда- anonymous
функции являются функциями, в то время как локальные функции - нет, но я не могу понять сценарий реального мира, где локальная функция имеет преимущества перед лямбда-выражениями
Любой пример будет высоко ценится. Спасибо.
Ответы:
Это было объяснено Мэдсом Торгерсеном из C # Design Notes, где впервые обсуждались локальные функции :
Чтобы расширить это еще, преимущества:
Производительность.
При создании лямбды должен быть создан делегат, который в данном случае является ненужным. Локальные функции - это просто функции, делегаты не нужны.
Кроме того, локальные функции более эффективны при захвате локальных переменных: лямбда-выражения обычно записывают переменные в класс, в то время как локальные функции могут использовать структуру (передается с использованием
ref
), что опять-таки позволяет избежать выделения.Это также означает, что вызов локальных функций обходится дешевле и может быть встроенным, что может еще больше повысить производительность.
Локальные функции могут быть рекурсивными.
Лямбды также могут быть рекурсивными, но для этого требуется неудобный код, в котором вы сначала назначаете
null
переменную-делегат, а затем лямбду. Локальные функции могут быть рекурсивными (в том числе взаимно рекурсивными).Локальные функции могут быть общими.
Лямбды не могут быть универсальными, поскольку они должны быть назначены переменной с конкретным типом (этот тип может использовать универсальные переменные из внешней области видимости, но это не одно и то же).
Локальные функции могут быть реализованы как итератор.
Lambdas не может использовать ключевое слово
yield return
(иyield break
) для реализацииIEnumerable<T>
функции -returning. Локальные функции могут.Локальные функции выглядят лучше.
Это не упоминается в приведенной выше цитате и может быть только моим личным уклоном, но я думаю, что нормальный синтаксис функции выглядит лучше, чем назначение лямбда-переменной для делегата. Локальные функции также более лаконичны.
Для сравнения:
источник
Func<int, int, int> f = (x, y) => x + y; f(arg1:1, arg2:1);
.object
. Итак, лямбды могут использовать структуру, но она должна быть в штучной упаковке, так что у вас все равно будет это дополнительное распределение.В дополнение к хорошему ответу svick, есть еще одно преимущество для локальных функций:
они могут быть определены в любом месте функции, даже после
return
оператора.источник
#region Helpers
нижнюю часть функции, чтобы избежать беспорядка в этой функции и, особенно, избежать беспорядка в основном классе.Если вы также задаетесь вопросом, как проверить локальную функцию, вам следует проверить JustMock, поскольку она имеет функциональные возможности для этого. Вот простой пример класса, который будет протестирован:
А вот как выглядит тест:
Вот ссылка на документацию JustMock .
Отказ от ответственности. Я один из разработчиков, отвечающих за JustMock .
источник
.DoNothing().OccursOnce();
а позже утверждают, что вызов был сделан путем вызоваMock.Assert(foo);
метода. Если вам интересно, как поддерживаются другие сценарии, вы можете прочитать нашу справочную статью Asserting Occurrence .Я использую встроенные функции, чтобы избежать давления при сборке мусора, особенно при работе с более длительными методами. Допустим, вы хотите получить 2 года или рыночные данные для данного символа тикера. Кроме того, можно упаковать много функциональности и бизнес-логики, если это необходимо.
все, что нужно сделать - это открыть сокетное соединение с сервером и зациклить данные, привязывающие событие к событию. Можно думать об этом так же, как проектируется класс, только один не пишет повсеместно вспомогательные методы, которые действительно работают только для одной функциональности. ниже приведен пример того, как это может выглядеть, обратите внимание, что я использую переменные, а методы "helper" находятся ниже, наконец. Наконец, я удаляю обработчики событий, если мой класс Exchange будет внешним / внедренным, у меня не будет зарегистрирован ни один ожидающий обработчик событий.
Вы можете увидеть преимущества, как указано ниже, здесь вы можете увидеть пример реализации. Надеюсь, что это помогает объяснить преимущества.
источник