C#中的闭包分配



我安装了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. 从匿名函数(如lambda)中调用此代码。

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

当您使用以上任何一种方法时,C#必须创建一个闭包来捕获闭包中使用的任何变量,这些变量的原始作用域在lambda之外(在第一种情况下),或者在yield/await之后的之前的用法(在第二种情况下)。

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

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

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

相关内容

  • 没有找到相关文章

最新更新