C#中的闭包分配

时间:2016-03-28 21:41:44

标签: c# closures roslyn cil

我已经安装了Clr堆分配分析器扩展,在项目中我看到了一些我不太懂的东西,我有一个带签名的方法

public Task<int> ExecuteAsync(string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
    {
        param = SetModificationValuesForGlobalRing(param);
        return _sqlPolicy.ExecuteAsync(async () =>
        {
            int result;
            using (var connection = new SqlConnection(_connectionString))
            {
                await connection.OpenAsync();
                result = await connection.ExecuteAsync(sql, param as object, transaction, commandTimeout, commandType);
            }
            return result;
        });
    }

这个工具'给我一个方法和所有参数

的警告
  

编译器将发出一个类,将其作为一个字段来保存,以便捕获此闭包。

我不知道为什么会出现这种情况,是否由于可选参数?

--------编辑将方法添加到方法------------

1 个答案:

答案 0 :(得分:9)

你必须是:

  1. 从匿名函数中调用此代码,如lambda。

    • 或 -
  2. 在某处使用yield / await关键字。

  3. 当你使用上述任何一个时,C#必须创建一个闭包来捕获闭包内使用的所有变量,这些变量的原始范围在lambda之外(在第一种情况下)或者在之前的用法在收益率/等待之后(在第二种情况下)。

    C#通过创建一个匿名类来捕获闭包 - 在编译时定义 - 在内存中。然后,它会在该匿名类上为其需要保留的每条信息创建一个字段。这可能导致对象实例的生命周期延长到闭包的生命周期或方法的生命周期与yield / await。

    有时寿命比你没有使用yield / await或lambda的时间长。在这种情况下,您可能会注意到内存使用率高于预期(因为垃圾收集器不会收集对象实例,直到闭包完全超出范围或者包含yield / await的方法已完成)。 / p>

    您看到的警告只是您尝试向您解释上述内容的工具,以便您知道预期此行为以及由此导致的内存使用量增加。