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