Лямбда-выражение

191
27 декабря 2017, 18:04

Рихтер пишет, что такое выражение:

internal sealed class AClass {
public static void CallbackWithoutNewingADelegateObject() {
  ThreadPool.QueueUserWorkItem( obj => Console.WriteLine(obj ), 5);
 }
}

Разворачивается в такое:

internal sealed class AClass {
// Это закрытое поле создано для кэширования делегата
// Преимущество: CallbackWithoutNewingADelegateObject не будет
// создавать новый объект при каждом вызове
// Недостатки: кэшированные объекты недоступны для сборщика мусора
[CompilerGenerated]
private static WaitCallback <>9__CachedAnonymousMethodDelegate1;
public static void CallbackWithoutNewingADelegateObject() {
if (<>9__CachedAnonymousMethodDelegate1 == null) {
// При первом вызове делегат создается и кэшируется
<>9__CachedAnonymousMethodDelegate1 =
new WaitCallback(<CallbackWithoutNewingADelegateObject>b__0);
}
  ThreadPool.QueueUserWorkItem(<>9__CachedAnonymousMethodDelegate1, 5);
}
[CompilerGenerated]
private static void <CallbackWithoutNewingADelegateObject>b__0(
Object obj) {
   Console.WriteLine(obj);
  }
}

А как будет выглядеть код, если используется несколько лябд?

Бдует кешироваться последний делегат?

Answer 1

То, во что компилируется код (т. наз. lowering: процесс упрощения кода, переписывания новых возможностей через старые), можно посмотреть на https://sharplab.io.

Вот такой пример:

using System;
using System.Threading;
internal sealed class AClass
{
    public static void CallbackWithoutNewingADelegateObject()
    {
        ThreadPool.QueueUserWorkItem(obj => Console.WriteLine(obj), 5);
        ThreadPool.QueueUserWorkItem(obj => Console.WriteLine(obj), 42);
    }
}

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

using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using System.Threading;
// атрибуты    
internal sealed class AClass
{
    [CompilerGenerated]
    [Serializable]
    private sealed class <>c
    {
        public static readonly AClass.<>c <>9 = new AClass.<>c();
        public static WaitCallback <>9__0_0;
        public static WaitCallback <>9__0_1;
        internal void <CallbackWithoutNewingADelegateObject>b__0_0(object obj)
        {
            Console.WriteLine(obj);
        }
        internal void <CallbackWithoutNewingADelegateObject>b__0_1(object obj)
        {
            Console.WriteLine(obj);
        }
    }
    public static void CallbackWithoutNewingADelegateObject()
    {
        WaitCallback arg_26_0;
        if ((arg_26_0 = AClass.<>c.<>9__0_0) == null)
        {
            AClass.<>c.<>9__0_0 = (arg_26_0 = new WaitCallback(
                AClass.<>c.<>9.<CallbackWithoutNewingADelegateObject>b__0_0));
        }
        ThreadPool.QueueUserWorkItem(arg_26_0, 5);
        WaitCallback arg_52_0;
        if ((arg_52_0 = AClass.<>c.<>9__0_1) == null)
        {
            AClass.<>c.<>9__0_1 = (arg_52_0 = new WaitCallback(
                AClass.<>c.<>9.<CallbackWithoutNewingADelegateObject>b__0_1));
        }
        ThreadPool.QueueUserWorkItem(arg_52_0, 42);
    }
}

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

Недавний пример: ранее делегаты кешировались так, как в вашем коде (private static WaitCallback), а теперь для него создаётся отдельный класс (private sealed class <>c). Фреймворк Moq, который исходил из старого варианта кодогенерации, отвалился.

READ ALSO
__line__ номер линии кода

__line__ номер линии кода

Не первый раз приходится писать

173
Передача параметров из C# в PostgreSQL

Передача параметров из C# в PostgreSQL

Никак не подберу правильную последовательность передачи параметровВылетает ошибка, что входная строка имела неверный формат

230
Аутентификация в ASP.NET MVC и AngularJS

Аутентификация в ASP.NET MVC и AngularJS

Доброго времени суток! Возникла следующая трудность, при передаче данных о пользователе, прошедшем аутентификацию в приложении ASPNET MVC на строну...

225
Xamarin android не подгружаются файлы проекта?

Xamarin android не подгружаются файлы проекта?

У Xamarin Forms для android проекта хочу разместить изображение по нажатию на кнопкуДля этого в MainPage

213