Что значит фраза "делегат кэшируется" в этом контексте (и вообще, что такое "кэшированный делегат и для чего он):
"В случае вызова SomeMethod(OtherMethod) — будет всегда создаваться делегат.
В случае вызова SomeMethod(x => OtherMethod(x)) — делегат будет кешироваться."?
Контекст отсюда
UPD
Между первым вызовом и вторым есть разница в MSIL'е, а именно такой код:
static void SomeMethod(Func<int, int> otherMethod)
{
otherMethod(1);
}
static int OtherMethod(int x)
{
return x;
}
static void Main(string[] args)
{
SomeMethod(OtherMethod); // 1
SomeMethod(x => OtherMethod(x)); // 2
SomeMethod(x => OtherMethod(x)); // 3
}
Будет преобразован примерно в следующий:
static void Main()
{
SomeMethod(new Func<int, int>(OtherMethod));
if (C.foo != null)
SomeMethod(C.foo)
else
{
C.foo = new Func<int, int>(c, C.b)
SomeMethod(C.foo);
}
if (C.foo1 != null)
SomeMethod(C.foo1)
else
{
C.foo1 = new Func<int, int>(c, C.b1)
SomeMethod(C.foo1);
}
}
[CompileGenerated]
class C
{
public static C c;
public static Func<int, int> foo;
public static Func<int, int> foo1;
static C()
{
c = new C();
}
C(){}
public int b(int x)
{
return OtherMethod(x);
}
public int b1(int x)
{
return OtherMethod(x);
}
}
Но как видно, компилятор на 3 вызов создал и инициализировал новую "кэшированную" переменную, а не использовал старую
Обсуждаемая тема — особенность кодогенерации текущей версии майкрософтовского фреймворка .NET.
Обсуждаемый код таков:
class Program
{
static void SomeMethod(Func<int, int> otherMethod) { otherMethod(1); }
static int OtherMethod(int x) { return x; }
static void Main(string[] args)
{
SomeMethod(OtherMethod); // 1
SomeMethod(x => OtherMethod(x)); // 2
}
}
При этом на текущий момент вызов
SomeMethod(OtherMethod); // 1
компилируется в аналог такого:
SomeMethod(new Func<int, int>(Program.OtherMethod));
(дело в том, что OtherMethod — не делегат, а метод, вот компилятор и любезно подставил создание делегата). А вызов
SomeMethod(x => OtherMethod(x)); // 2
— в аналог такого (по поводу LambdaClass смотрите здесь):
Func<int, int> f = LambdaClass.cached_f;
// cached_f - невидимое статическое поле в классе LambdaClass, который содержит лямбду
if (f == null)
{
f = LambdaClass.cached_f = new Func<int, int>(LambdaClass.method_f);
}
Program.SomeMethod(f);
То есть значение делегата (Func<int, int>) и вправду кешируется.
Но я бы не придавал этому факту большого значения: кодогенерация даже в Microsoft .NET меняется со временем (вот недавние изменения в кодогенерации лямбд, а вот недоумение команды, которая рассчитывала в своём коде на недокументированные особенности), а уж кодогенерация в других имплементациях имеет право отличаться и подавно.
Продвижение своими сайтами как стратегия роста и независимости