代码检查:访问已释放的捕获变量
首先,让我们确保您理解什么是 闭包。 简单来说,C# 中的闭包是一个 lambda 表达式或匿名方法,它捕获了外部作用域中的一些变量。 以下是最简单的示例:
// A self-contained lambda. Not a closure.
Action printOne = () => { Console.WriteLine("one"); };
// A closure – a lambda that captures a variable from an outer scope.
string myStr = "one";
Action print = () => { Console.WriteLine(myStr); };
在上述示例中, 打印 将捕获变量 myStr (而不是其 值 ),并且仅在您调用 打印() 时获取 myStr 的 值。
在更复杂的场景中,当闭包定义在一个变化的上下文中时,它可能不会按预期运行。
其中一种可能发生的情况是闭包定义在 示意图 语句内部:
void Foo(string fileName, string text)
{
using (var writer = new StreamWriter(fileName))
{
ExecuteDelayed(() => { writer.Write(text); });
}
}
private static void ExecuteDelayed(Action action)
{
// execute action
}
在上述代码中,JetBrains Rider 会针对 writer.Write(text); 发出 访问已释放的闭包警告。 原因是 ExecuteDelayed() 可能在 写入器 的作用域被释放后执行 lambda,这将导致运行时异常。
如果 ExecuteDelayed() 在堆栈上完成了 lambda 的处理,您可以使用 InstantHandle属性标记 操作 参数:
private static void ExecuteDelayed([InstantHandle]Action action)
{
// execute action
}
这将告诉 JetBrains Rider 的代码分析引擎,在这种上下文中使用 ExecuteDelayed() 是安全的,不会发出任何警告。
最后修改日期: 2025年 9月 26日