2016-04-27 46 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表示要麼返回一個有效的對象,要麼拋出異常。沒有機會返回處置的對象引用。

相關問題