Работа с методами, которые возвращают анонимные методы

Если у меня есть такой класс:

public class SomeClass
{
    public Action<string> SomeAction { get; set; }

    public SomeClass()
    {
        SomeAction = GetSomeAnonymousMethod();
    }

    private Action<string> GetSomeAnonymousMethod()
    {
        return (text) =>
        {
            Console.WriteLine(text);
        };
    }
}

Что происходит, когда я делаю новый экземпляр SomeClass? У меня сложилось впечатление, что конструктор просто вызывает GetSomeAnonymousMethod(), который возвращает новый экземпляр делегата (который содержит только ссылку на сгенерированный компилятором метод поддержки анонимного метода) и назначает его SomeAction имущество.

Может кто-то подтвердить, или происходит что-то более зловещее?

2 ответа

Решение

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

Так что это больше похоже на это - по крайней мере, при компиляции с MS-компилятором:

public class SomeClass
{
    private static Action<string> cachedAction;
    public Action<string> SomeAction { get; set; }

    public SomeClass()
    {
        SomeAction = GetSomeAnonymousMethod();
    }

    private Action<string> GetSomeAnonymousMethod()
    {
        Action<string> action = cachedAction;
        if (action == null)
        {
            action = AnonymousMethodImplementation;
            cachedAction = action;
        }
        return action;
    }

    private static void AnonymousMethodImplementation(string text)
    {
        Console.WriteLine(text);
    }
}

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

Как всегда, чтобы увидеть детали того, что делает компилятор, вы всегда можете использовать ildasm (или Reflector в режиме IL, например) и посмотреть сгенерированный IL.

Может кто-то подтвердить, или происходит что-то более зловещее?

Похоже, это очередная тайная акция в рамках событий новой и второй холодной войны!

Да, ваш конструктор делает то, что вы описываете в своем вопросе.

Я бы объяснил, что анонимный делегат преобразуется в Action<string> используя вывод типа делегата.

Например, следующая строка кода:

return (text) =>
        {
            Console.WriteLine(text);
        };

... выводится для:

return new Action<string>((text) => 
{
     Console.WriteLine(text);
});
Другие вопросы по тегам