c# – 为什么编译器不能通过内联优化闭包变量?

我有一个像这样的Main方法:
static void Main(string[] args)
{
     var b = new byte[1024 * 1024];

     Func<double> f = () =>
     {
         new Random().NextBytes(b);
         return b.Cast<int>().Average();
     };

     var avg = f();
     Console.WriteLine(avg);
}

由于我在这里访问局部变量b,编译器创建一个类来捕获该变量,b成为该类的字段.然后,只要编译器生成类的生命周期,它就会存在,并且它会导致内存泄漏.即使b超出范围(可能不是在这种情况下,但想象这是在另一个方法而不是Main),字节数组将不会被释放.

我想知道的是,因为我在声明Func后没有访问或修改b,为什么编译器不能内联该局部变量而不打扰创建类?像这样:

Func<double> f = () =>
{
    var b = new byte[1024 * 1024];
    new Random().NextBytes(b);
    return b.Cast<int>().Average();
};

我在Debug和Release模式下编译了这段代码,DisplayClass在两者中生成:

这是不是作为优化实现还是我缺少什么?

解决方法

Is this just not implemented as an optimization or is there anything I am missing?

对于您给出的具体示例,您可能不希望进行代码转换,因为它会更改程序的语义.如果new抛出异常,在原始程序中它应该在执行委托之前这样做,并且在转换中,副作用被推迟.这是否是一个应该保留的重要财产是值得商榷的. (这样做也会给调试器带来问题;调试器必须假装闭包类的元素是包含方法体的本地元素,并且这种优化可能会使其进一步复杂化.)

然而,更普遍的一点是密切相关.如果您知道封闭变量仅用于其值,则可以执行许多优化.

当我参加编译团队时 – 我在2012年离职 – 我和Neal Gafter考虑实施这样的优化,以及一些更复杂的优化,旨在降低昂贵对象的生命周期长时间延长的可能性.

旁白:最复杂的场景中最简单的是:我们将两个lambdas转换为委托;一个存储在一个短期变量中,并在一个包含对昂贵对象的引用的本地上关闭;一个存储在一个长期存在的变量中,并在一个引用廉价对象的本地上关闭.即使没有使用,昂贵的物体也会存在长寿命变量.更一般地,可以基于封闭关系将多个闭包构造为分区;当时我们只基于嵌套来分区闭包;在同一嵌套层面的封闭是一个封闭.给定的场景很少见,并且有明显的解决方法,但如果它根本没有发生会很好.

我们没有这样做,因为在我们实施Roslyn期间有更重要的优化和功能,我们不想为已经很长的时间表增加风险.

我们可以自信地执行这样的优化,因为在C#中很容易知道本地何时被别名化,因此您可以确定是否在创建闭包之后写入它.

我不知道这些优化是否已经同时实施;可能不是.

我也不知道编译器是否对C#7本地函数进行了这样的优化,但我怀疑答案是肯定的.看看如果尝试本地功能会发生什么!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


1:最直白的循环遍历方法,可以分为遍历key--value键值对以及所有的key两种表现形式2:用Linq的方式去查询(当然了这里要添加对应的命名空间 using System.Linq)如下为一个十分简单的代码示例:private void GetDicKeyByValue(){ Dicti...
private void ClearTextBox(){ foreach (var control in pnlDetail.Controls) { if (!(control is TextBox)) continue; var txtBox = (TextBox)control; txtBox.
原文叫看《墨攻》理解IOC概念 2006年多部贺岁大片以让人应接不暇的频率纷至沓来,其中张之亮的《墨攻》算是比较出彩的一部,讲述了战国时期墨家人革离帮助梁 国反抗赵国侵略的个人英雄主义故事,恢宏壮阔,浑雄凝重的历史场面相当震撼。其中有一个场景:当刘德华所饰的墨者革离到达梁国都城 下,城上梁国守军问:
System.Data.ConstraintException: Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints.
Request.Form value was detected from the client在使用ASP.NET MVC3 开发系统的用了百度的UEditor编辑器提交表单时遇到检测到有潜在危险的 Request.Form,我百度一下,试了网上的方法,都没用。要在Web.config增加&lt;h
右击文件夹-&gt;安全选项卡-&gt;添加-&gt;高级-&gt;立即查找Windows Server 2003:请您在目录添加IIS来宾帐号(IUSR_Hostname)的只读权限,以及Network Service组的读写修改权限。Windows Server 2000:请您在目录添加IIS来
&lt;compilationdebug=&quot;true&quot;&gt;&lt;buildProviders&gt;&lt;addextension=&quot;.html&quot;type=&quot;System.Web.Compilation.PageBuildProvider&q
在ASP.NET MVC 中 Spring.NET 配置注入的时候,下面这方式是可行的。&lt;spring&gt; &lt;context&gt; &lt;resource uri=&quot;config://spring/objects&quot; /&gt; &lt;/context&gt;
Stopwatch stopwatch = new Stopwatch();stopwatch.Start();。。。。。中间代码。。。&#x9;stopwatch.Stop();&#x9;long result = stopwatch.ElapsedMilliseconds;sqlBulkCopy.Close()
问题描述 在asp.net mvc 下配置ueditor图片上传时总是提示:缺少十六进制字符错误(IE下提示),起初还以为是我上传的图片名称中有中文字符所致,后来我又上传了英文字符名字的图片发现还是一样的错误提示:◆无赖之下只好到火狐下看错误的详情:◆第二个错误我无法解决,先看第一个,输入地址显示错
已经安装net2.0 和3.5 ,但IIS里面却只有1.1开始→运行→CMDC:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -i按回车键后便会开始自动安装,安装完重启一下IIS在IIS中ASP.NET选项卡便可以看到。注
根据传进来不同的值,调用不同的方法View Code protected void btn_SwitchClick(object sender, EventArgs e){ string result = &quot;&quot;; switch (ddlMethod.SelectedValue)
整理两个 在C#中,用正则表达式 获取网页源代码标签的属性或值的方法 :1、获取标签中的值: CSDN 结果:CSDN/// /// 获取字符中指定标签的值 /// /// 字符串 /// 标签 /// 值 public static string GetTitleContent(string st
/// &lt;summary&gt;/// 集合装换DataTable/// &lt;/summary&gt;/// &lt;param name=&quot;list&quot;&gt;集合&lt;/param&gt;/// &lt;returns&gt;&lt;/returns&gt;publ
将目录下面所有的 .cs 文件合并到一个 code.cs 文件中,写著作权复制代码时的必备良药 @echo off echo 将该目录下所有.cs文件的内容合并到一个 code.cs 文件中! pause dir /ad/s/b &gt; folderPath.txt md codeTemp for
做接口开发的时候,往往接受参数或返回值是一个XML的字符串。如下图,不方便辨识 两种方法, 1.将它保存为xxx.xml,然后用浏览器打开。这种方法稍微有些麻烦。 2.使用 UltraEdit 工具
一个字段控制多个状态选项private void GenerateAdvice_OnClick(object sender, RoutedEventArgs e){ TestStatus c1 = TestStatus.A | TestStatus.C | TestStatus.E; v...
效果如下: 代码如下:
StartUp.cs public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseEndpoints(endpoints =&gt; { endpoints.MapControllerRoute(