为什么代码分析会在此方法上触发 CA2000?
Why does Code Analysis fire CA2000 on this method?
Visual Studio 代码分析在此方法中的 monitor
变量上生成警告 "Dispose objects before losing scope" (CA2000)。
private void MonitorJob(IJob job, CancellationToken cancellationToken)
{
var monitor = new JobMonitor(job, _backend); // <- CA2000
try
{
var task = monitor.Run(cancellationToken);
_activeJobs[task] = monitor;
}
catch
{
monitor.Dispose();
throw;
}
}
我了解 CA2000 的作用,而且我通常能够找出我的代码违反规则的原因并进行适当的更改。
然而,在这种情况下,我很困惑 - 这真的是误报,还是我遗漏了什么?
使用 Visual Studio 2015 企业版,面向 .NET 4.5,使用 C# 6。
我假设 _activeJobs[task] = monitor;
是一个简单的赋值并且不会抛出异常。如果这样,将存储监视器与创建监视器分开。
private void MonitorJob(IJob job, CancellationToken cancellationToken)
{
Task task;
var monitor = CreateJobMonitor(job, _backend, out task);
_activeJobs[task] = monitor;
}
private JobMonitor CreateJobMonitor(IJob job, CancellationToken cancellationToken, out Task task)
{
var monitor = new JobMonitor(job, _backend);
try
{
task = monitor.Run(cancellationToken);
return monitor;
}
catch
{
monitor.Dispose();
throw;
}
这样,CreateJobMonitor 意味着 return 获取有效对象或抛出异常。没有机会 return 处置对象引用。
如果此处抛出异常,您可能会泄漏此一次性用品:
private void MonitorJob(IJob job, CancellationToken cancellationToken)
{
var monitor = new JobMonitor(job, _backend);
// <- Exception
try
{
var task = monitor.Run(cancellationToken);
_activeJobs[task] = monitor;
}
catch
{
monitor.Dispose();
throw;
}
}
这可能是由 ThreadAbortException
或运行时注入线程的任何其他异常引起的。我建议在 try
块之外声明变量,但在内部分配它。此外,将其设置为 null
成功分配给 _activeJobs
.
private void MonitorJob(IJob job, CancellationToken cancellationToken)
{
JobMonitor monitor;
try
{
monitor = new JobMonitor(job, _backend);
var task = monitor.Run(cancellationToken);
_activeJobs[task] = monitor;
monitor = null;
}
finally
{
if(monitor!=null)
{
monitor.Dispose();
}
throw;
}
}
即便如此,关闭警告可能还不够,此时我建议为其添加抑制。
Visual Studio 代码分析在此方法中的 monitor
变量上生成警告 "Dispose objects before losing scope" (CA2000)。
private void MonitorJob(IJob job, CancellationToken cancellationToken)
{
var monitor = new JobMonitor(job, _backend); // <- CA2000
try
{
var task = monitor.Run(cancellationToken);
_activeJobs[task] = monitor;
}
catch
{
monitor.Dispose();
throw;
}
}
我了解 CA2000 的作用,而且我通常能够找出我的代码违反规则的原因并进行适当的更改。
然而,在这种情况下,我很困惑 - 这真的是误报,还是我遗漏了什么?
使用 Visual Studio 2015 企业版,面向 .NET 4.5,使用 C# 6。
我假设 _activeJobs[task] = monitor;
是一个简单的赋值并且不会抛出异常。如果这样,将存储监视器与创建监视器分开。
private void MonitorJob(IJob job, CancellationToken cancellationToken)
{
Task task;
var monitor = CreateJobMonitor(job, _backend, out task);
_activeJobs[task] = monitor;
}
private JobMonitor CreateJobMonitor(IJob job, CancellationToken cancellationToken, out Task task)
{
var monitor = new JobMonitor(job, _backend);
try
{
task = monitor.Run(cancellationToken);
return monitor;
}
catch
{
monitor.Dispose();
throw;
}
这样,CreateJobMonitor 意味着 return 获取有效对象或抛出异常。没有机会 return 处置对象引用。
如果此处抛出异常,您可能会泄漏此一次性用品:
private void MonitorJob(IJob job, CancellationToken cancellationToken)
{
var monitor = new JobMonitor(job, _backend);
// <- Exception
try
{
var task = monitor.Run(cancellationToken);
_activeJobs[task] = monitor;
}
catch
{
monitor.Dispose();
throw;
}
}
这可能是由 ThreadAbortException
或运行时注入线程的任何其他异常引起的。我建议在 try
块之外声明变量,但在内部分配它。此外,将其设置为 null
成功分配给 _activeJobs
.
private void MonitorJob(IJob job, CancellationToken cancellationToken)
{
JobMonitor monitor;
try
{
monitor = new JobMonitor(job, _backend);
var task = monitor.Run(cancellationToken);
_activeJobs[task] = monitor;
monitor = null;
}
finally
{
if(monitor!=null)
{
monitor.Dispose();
}
throw;
}
}
即便如此,关闭警告可能还不够,此时我建议为其添加抑制。