在我的WPF应用程序中,我的代码中有以下使用DataGrid的方法:

List<IColumn> GetColumns()
{
    return _columnItems
        .Where(column => column is TextColumn<T> textColumn && 
                         textColumn.IsColumnEnabled
        )
        .ToList();
}

即使在关闭包含相应datagrid的对话框后,此代码仍保留在内存中.我可以通过判断dotMemoryJetBrains来看到它,我有一个Func<IColumn, bool>作为GC根,保持我的DataGrid.

然而,如果我只执行这个简单的更改:

List<IColumn> GetColumns()
{
    var columnsToReturn = new List<IColumn>();
    foreach (var column in _columnItems)
    {
        if (column is TextColumn<T> textColumn && textColumn.IsColumnEnabled)
            columnsToReturn.Add(textColumn);
    }

    return columnsToReturn ;
}

内存泄漏消失了,DataGrid的实例在关闭对话框后被清除,这个曾经是GC根的Func也消失了.

虽然我很高兴我已经解决了内存泄漏问题,I would like to understand what's going on?

我假设它与Linq投影有关,这是缓存条目的逻辑,尽管我有点惊讶,因为泄漏的代码最后有ToList(),这本来应该执行查询的.我的长语法避开了LinqFunc(WHERE),因此"切断"了dotMemory中的 twig .

我的意思是,我已经从这个方法返回了Func次执行,因为我已经调用了ToList(),所以无论使用什么方法的输出都使用返回的列表,那么为什么LinqIEnumerable还会把Func保存在内存中呢?

推荐答案

哇,这是由于编译器优化造成的.

你可以在这里找到所有相关的信息:https://stackoverflow.com/a/46963119/3707896

简而言之,编译器创建了一个子类,将我的函数(lambda表达式)作为该类的实例方法,在静态字段中创建了该类的单个实例,最后创建了一个静态字段,其中我的Func引用了我的方法.因此,GC不能收集由编译器生成的那些静态成员也就不足为奇了.

#

Csharp相关问答推荐

是否可以将gltf转换为字节数组,然后将字节数组转换回文件?

我应该将新的httpReportMessage()包装在using声明中吗?

ß != ss与ICU进行不区分大小写的比较

在实际上是List T的 IESEARCH上多次调用First()是否不好?

EF Core:看不到任何查询日志(log)?

是否可以使用EF—Core进行临时部分更新?

实体框架核心上是否支持使用NPGSQL的字符串聚合?

. net依赖注入如何避免服务类中的新

Azure DEVOPS找不到定制的Nuget包

自动映射程序在GroupBy之后使用项目

如何使用新的Microsoft.IdentityModel.JsonWebToken创建JwtSecurityToken?

ASP.NET配置kestrel以使用Windows证书存储中的HTTPS

集合表达式没有目标类型

WPF动态设置弹出窗口水平偏移

使用可空引用类型时C#接口实现错误

使用LibraryImport在多个dll中导入相同的函数

嵌套Blazor组件内的验证

将两个JSON文件与覆盖值的主文件合并

为什么我不能在固定语句中使用外部函数?

异步等待,如何在Windows窗体中使用它们?