加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 将强制类型委托的匿名lambda强制转换为禁用编译器缓存吗?

发布时间:2020-12-16 01:28:47 所属栏目:百科 来源:网络整理
导读:我试图理解编译器驱动的委托缓存的边缘情况,以避免内存分配. 例如,根据我的理解,此委托被缓存到单个实例并重用,因为它不会关闭任何局部变量: int[] set = new [] { 1,2,3,4,5,6 };var subset = set.Where(x = x % 2 == 0); 现在我遇到一些情况,我生成的代码
我试图理解编译器驱动的委托缓存的边缘情况,以避免内存分配.

例如,根据我的理解,此委托被缓存到单个实例并重用,因为它不会关闭任何局部变量:

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

为了避免这种情况,我看到两个选择:

>使用构造函数:

var result = (new Func<int,bool>(x => x % 2 == 0)).Invoke(5);

>投射匿名代表:

var result = ((Func<int,bool>)(x => x % 2 == 0)).Invoke(5);

我假设编译器不会在选项#1中缓存委托,但我不确定它是否会在#2中.

这记录在哪里?

解决方法

I’m assuming the compiler will not cache the delegate in option #1,but I’m not sure if it will in #2.

事实上,它可以在两种情况下,并且它们是捆绑在一起的.

从ECMA C#5规范,第7.6.10.5节:

The binding-time processing of a delegate-creation-expression of the form new D(E),where D is a delegate-type and E is an expression,consists of the following steps:

  • If E is an anonymous function,the delegate creation expression is processed in the same way as an anonymous function conversion (§6.5) from E to D.

所以基本上两者都以同样的方式处理.在这两种情况下都可以缓存.是的,“新的并不一定意味着新的”是非常奇怪的.

为了表明这一点,让我们写一个非常简单的程序:

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;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读