Работа с методами, которые возвращают анонимные методы
Если у меня есть такой класс:
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);
});