Производительность назначения простого лямбда-выражения или локальной функции делегату - PullRequest
0 голосов
/ 18 мая 2018

При использовании очень простого выражения в качестве ключа для создания ILookup с Enumerable.ToLookup<TSource, TKey> Method (IEnumerable<TSource>, Func<TSource, TKey>) я могу использовать лямбда-выражение:

var lk = myItems.ToLookup((x) => x.Name);

или локальную функцию:

var lk = myItems.ToLookup(ByName);

string ByName(MyClass x)
{
     return x.Name;
}

Мне любопытно, есть ли разница в этом простом случае.

В его ответ на Локальная функция против Lambda C # 7.0 ТАК пользователь svick дает хороший аргумент, почему - в целом - локальные функции предпочтительнее лямбд.

Важным моментом является разница в производительности:

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

Но так как мы передаем его в ToLookup(), делегат в любом случае создается.Есть ли разница в производительности?
Я могу себе представить, что компилятор должен создавать новую лямбду-делегат для каждого вызова myItems.ToLookup, тогда как для локального метода необходим только один экземпляр делегата;это правда?

Вторая разница в производительности в svick's answer - захват переменных и создание замыканий:

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

Однако, поскольку в выражении не используются переменные из внешней области видимости, необязательно должно быть замыкание, как указано Ридом Копси и расширено на Eric Lippert в ответ на Являются ли лямбда-выражения в замыканиях C #? :

Лямбда может быть реализована с использованием замыкания, но оно не обязательно само по себе замыкание.- Рид Копси
[...]
функция, которая может рассматриваться как объект, является просто делегатом.Что делает лямбду замыканием, так это то, что она фиксирует свои внешние переменные.- Эрик Липперт

Это несколько противоречит Эрик Липперт Сам является его ответом на Назначением локальных функций делегатам Эрик Липперт объясняет локальную функцию как именованную лямбду:

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

Но это на уровне меньшей технической детализации и для делегатов лямбда-функций / local, которые do захватывают переменные внешней области видимости.

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

1 Ответ

0 голосов
/ 18 мая 2018

В текущей версии компилятора (Roslyn 2.8.0) версия с лямбда-кодом более эффективна, потому что она кэширует делегат.

Просмотр IL кода, в котором есть ваши двасэмплы в отдельных методах , это эффективно:

sealed class HelperClass
{
    public static readonly HelperClass Instance = new HelperClass();

    public static Func<MyClass, string> CachedDelegate;

    internal string LambdaByName(MyClass x)
    {
        return x.Name;
    }

    internal string LocalFunctionByName(MyClass x)
    {
        return x.Name;
    }
}

void Lambda(IEnumerable<MyClass> myItems)
{
    var lk = myItems.ToLookup(HelperClass.CachedDelegate ??
        (HelperClass.CachedDelegate =
            new Func<MyClass, string>(HelperClass.Instance.LambdaByName)));
}

void LocalFunction(IEnumerable<MyClass> myItems)
{
    var lk = myItems.ToLookup(
        new Func<MyClass, string>(HelperClass.Instance.LocalFunctionByName)));
}

Обратите внимание, как Lambda выделяет делегата только один раз и затем использует кэшированный делегат, тогда как LocalFunction выделяет делегата каждый раз.Это делает Lambda более эффективным в данном конкретном случае.

Хотя на GitHub есть предложение изменить компилятор, чтобы сделать LocalFunction столь же эффективным, как Lambda.

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