2016-04-27 119 views
4

Visual Studio代码分析在此方法中的monitor变量上生成警告“在丢失范围之前丢弃对象”(CA2000)。为什么代码分析在这个方法上激发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

+2

对于一个工具来说,Run()方法总是会抛出一个异常。或者假设你这么做,它可能会在以后放置,因为你将它存储在_activeJobs中。只要压制警告。 –

+0

不使用'使用'的原因是什么? – qxg

+0

@qxg你如何在这里使用它? – zerkms

回答

2

如果有异常抛出在这里你可以泄露这个一次性的:

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块之外声明该变量,但将其分配在内。另外,将它成功分配到_activeJobs时,将其设置为null

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; 
    } 
} 

即使是这样,虽然,它可能没有足够的闭嘴了警告,在这一点上,我会建议增加抑制它。

+0

这一切都有道理,但留给我一个(次要)后续问题:为什么不在同一个项目中的其他*代码也遵循模式'var x = new Y(); try..catch'也违反了CA2000? – Bevan

+0

例如,此处接受的答案http://stackoverflow.com/a/9663477/30280在建议的“安全”版本的“CreateFirstObject()”中恰好具有此结构。 – Bevan

0

我认为_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表示要么返回一个有效的对象,要么抛出异常。没有机会返回处置的对象引用。

相关问题