简体   繁体   English

C# 中的闭包分配

[英]Closure allocations in C#

I've installed the Clr Heap Allocation Analyzer extension and in a project I see something that I quite don't understand, I've got a method with a signature我已经安装了 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;
    });
}

This tools' giving me a warning on the method and all the parameters that says这个工具给我一个关于方法和所有参数的警告

The compiler will emit a class that will hold this as a field to allow capturing of this closure.编译器将发出一个类,将它作为一个字段保存,以允许捕获此闭包。

I don't know why this behaviour happens, is it due to the optional parameters?我不知道为什么会发生这种行为,是由于可选参数吗?

You must be:你必须是:

  1. Calling this code from within an anonymous function, like a lambda.从匿名函数中调用此代码,如 lambda。

    • or -或 -
  2. Using the yield/await keyword somewhere.在某处使用 yield/await 关键字。

When you use either of the above, C# must create a closure to capture any variables used within the closure that have an originating scope outside of your lambda (in the first case) or usage before and after the yield/await (in the second case).当您使用上述任一方法时,C# 必须创建一个闭包来捕获闭包中使用的任何变量,这些变量的原始范围在 lambda 之外(在第一种情况下)或在 yield/await 之前之后的使用(在第二种情况下) )。

C# captures the closure by creating an anonymous class -- defined at compile-time -- in memory . C# 通过在内存中创建一个匿名类(在编译时定义)来捕获闭包 It then creates a field on that anonymous class for each piece of information it needs to persist.然后,它在该匿名类上为它需要保留的每条信息创建一个字段。 This can result in an object instance's lifetime being extended for the life of the closure or the life of the method with the yield/await.这可能导致对象实例的生命周期延长至闭包的生命周期或具有 yield/await 的方法的生命周期。

Sometimes the lifetime is longer than had you NOT used yield/await or the lambda.有时生命周期比没有使用 yield/await 或 lambda 的生命周期更长。 In that case, you might notice memory usage that is higher than you expected (as the garbage collector won't collect the object instance until the closure is completely out of scope or the method containing the yield/await has completed).在这种情况下,您可能会注意到内存使用量高于预期(因为垃圾收集器不会收集对象实例,直到闭包完全超出范围或包含 yield/await 的方法已完成)。

The warning you see is simply your tool trying to explain the above to you , so that you know to expect this behavior and the resulting potential increase in memory usage.您看到的警告只是您的工具试图向您解释上述内容,以便您知道预期这种行为以及由此产生的内存使用量的潜在增加。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM