using 语句中的“访问已处理的关闭”警告

Cas*_*ite 3 c# resharper idisposable using-statement

我正在使用“使用语句”来确保正确清理 StreamWriter。

using (StreamWriter fout = new StreamWriter(tempFile))
{
    data.ForEach(line => fout?.WriteLine(line));
}
Run Code Online (Sandbox Code Playgroud)

我收到 ReSharper 警告“访问已处理的关闭”,据我所知,这是因为变量fout可能已关闭。我知道在某些用途中可能会发生,但在这种情况下,是否有可能fout在调用时已经被处理WriteLine

Cor*_*rey 5

欢迎使用堆栈溢出。

ReSharper 的Access to disposed closure警告应该只在 LINQ 延迟执行捕获对可能在执行发生之前处理的闭包的引用时发生。

这里是否是这种情况取决于ForEach您调用的方法。如果您正在调用,List.ForEach那么您不会构成延迟执行链,因此fout显然对每次调用都有效。当涉及到这种方法时,ReSharper 当然应该更了解。

但是还有其他ForEach方法,包括自定义方法,ReSharper 可能不知道或实际上可能会延迟。如果它们写得很好,那么它们将阻塞直到它们完成,但我已经看到自定义ForEach扩展方法没有。由于 ReSharper 无法确定,除非代码InstantHandle通过 action 参数上的注释告诉它,因此它会警告您。

如果你在List.ForEach这里工作,那么我建议你放弃它,转而使用一个很好的旧foreach语句。对于其他扩展,请查明它是否会阻塞或是否有可能在任何情况下推迟执行。 Observable.ForEach并且Parallel.ForEach两者似乎都会阻止执行,直到集合被完全处理或事件源关闭。其他代码可能不会这样做,事后追踪这样的错误可能会很痛苦。如果可以,请检查方法的来源,如果无法访问来源,请联系库开发人员。

一旦您确定这ForEach肯定会阻塞并且永远不会推迟执行,那么您可以继续并抑制警告:

// ReSharper disable AccessToDisposedClosure
data.ForEach(line => fout?.WriteLine(line));
// ReSharper restore AccessToDisposedClosure
Run Code Online (Sandbox Code Playgroud)