簡體   English   中英

將匿名lambda強制轉換為強類型委托會禁用編譯器緩存嗎?

[英]Does casting an anonymous lambda to a strongly typed delegate disable compiler caching?

我試圖理解編譯器驅動的委托緩存的邊緣情況,以避免內存分配。

例如,根據我的理解,此委托被緩存到單個實例並重用,因為它不會關閉任何局部變量:

int[] set = new [] { 1, 2, 3, 4, 5, 6 };
var subset = set.Where(x => x % 2 == 0);

現在我遇到一些情況,我生成的代碼可能想直接調用委托,因此匿名方法無效C#,如下所示:

var result = (x => x % 2 == 0).Invoke(5); // Invalid

為了避免這種情況,我看到兩個選擇:

  1. 使用構造函數:
var result = (new Func<int, bool>(x => x % 2 == 0)).Invoke(5);
  1. 投射匿名代表:
var result = ((Func<int, bool>)(x => x % 2 == 0)).Invoke(5);

我假設編譯器不會在選項#1中緩存委托,但我不確定它是否會在#2中。

這記錄在哪里?

我假設編譯器不會在選項#1中緩存委托,但我不確定它是否會在#2中。

事實上,它可以在兩種情況下,並且它們是捆綁在一起的。

從ECMA C#5規范,第7.6.10.5節:

新D(E)形式的委托創建表達式的綁定時處理,其中D是委托類型,E是表達式,包括以下步驟:

  • ...
  • 如果E是匿名函數,則委托創建表達式的處理方式與從E到D的匿名函數轉換(第6.5節)相同。
  • ...

所以基本上兩者都以同樣的方式處理。 在這兩種情況下都可以緩存。 是的,“新的並不一定意味着新的”是非常奇怪的。

為了表明這一點,讓我們寫一個非常簡單的程序:

using System;

public class Program
{
    public static void Main()
    {
        var func = new Func<int, bool>(x => x % 2 == 0);
    }
}

這是我的機器上的Main方法的IL(誠然使用C#8預覽編譯器構建,但我希望它會持續一段時間):

.method public hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       29 (0x1d)
  .maxstack  8
  IL_0000:  ldsfld     class [mscorlib]System.Func`2<int32,bool> Program/'<>c'::'<>9__0_0'
  IL_0005:  brtrue.s   IL_001c
  IL_0007:  ldsfld     class Program/'<>c' Program/'<>c'::'<>9'
  IL_000c:  ldftn      instance bool Program/'<>c'::'<Main>b__0_0'(int32)
  IL_0012:  newobj     instance void class [mscorlib]System.Func`2<int32,bool>::.ctor(object,
                                                                                      native int)
  IL_0017:  stsfld     class [mscorlib]System.Func`2<int32,bool> Program/'<>c'::'<>9__0_0'
  IL_001c:  ret
} // end of method Program::Main

那是有效的:

Func<int, bool> func;
func = cache;
if (func == null)
{
    func = new Func<int, bool>(GeneratedPrivateMethod);
    cache = func;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM