2012-05-20 83 views
2

我有一個非常大的項目,我儘量保持乾淨整潔。當我在Visual Studio中運行代碼分析器時,我得到一個可靠性錯誤,我覺得很煩人。我真的很想學習如何解決它。這是我正在做的一個簡單的例子。如何正確處理此代碼?

這裏是警告。

警告1 CA2000:Microsoft.Reliability:在方法 'MyExampleClassForStackOverflow.AddFeed(字符串)',所有的引用之前請對象System.IDisposable.Dispose '新FeedClassExamle()' 到它超出範圍。

這裏是我的示例代碼:

class MyExampleClassForStackOverflow : IDisposable 
{ 
    public ConcurrentDictionary<string, FeedClassExamle> Feeds { get; set; } 

    public void AddFeed(string id) 
    { 
     //The warning is coming from this code block. 
     //In the full code, the feed classes collects data on a specific 
     //interval and feeds them back using events. 
     //I have a bunch of them and they need to be accessible so I 
     //store them in dictionaries using keys to effeciently find them. 
     Feeds.TryAdd(id, new FeedClassExamle()); 
     Feeds[id].Start(); 
    } 
    public void Dispose() 
    { 
     foreach (var item in Feeds) 
      item.Value.Dispose(); 
    } 
} 

class FeedClassExamle : IDisposable 
{ 
    public void Start() 
    { 

    } 
    public void Dispose() 
    { 

    } 
} 

爲了測試代碼,使用方法:

using (var example = new MyExampleClassForStackOverflow()) 
{ 

} 

任何建議將受到歡迎。

+0

好問題。我一直禁止這種警告在這種情況下......這將是很好的瞭解,如果有什麼解決辦法 – 6opuc

回答

1

警告存在:

public void AddFeed(string id) 
{ 
    FeedClassExample fce = new FeedClassExamle(); 
    if (!Feeds.TryAdd(id, fce)) 
    { 
     fce.Dispose(); 
    } 
    Feeds[id].Start(); 
} 
+0

是的,與析構函數好主意。我可以這樣做。關於創建一個新實例(如果已經存在的話),這在我的主代碼中進行了介紹。在這裏我只是用來演示如何重現警告的簡單示例中缺少。 – BlueVoodoo

1

的對象沒有被處理掉TryAdd失敗的,所以儘量明確地這樣做:

if (!Feeds.ContainsKey(id)) { 
    Feeds.GetOrAdd(id, new FeedClassExamle()); 
} 
+0

我嘗試過,但仍然得到: 警告 CA2000:Microsoft.Reliability:在方法「MyExampleClassForStackOverflow.AddFeed(串)',在對象'fce'調用System.IDisposable.Dispose之前,它的所有引用都超出了範圍。 – BlueVoodoo

+0

如果你有'Feeds [id] = new FeedClassExamle();'嗎? –

+0

這似乎與'ConcurrentDictionary'類有關 - 當標準字典類取代時,消息消失。它看起來像代碼分析沒有意識到ConcurrentDictionary保持參考。 – Richard

0

只有當它需要添加創建實例因爲代碼分析工具無法確定對象是否會正確放置。您的代碼被寫入的方式實際上不會正確處理該對象,但修復代碼可能不會消除警告。

基本上,需要發生的是每個AddFeed方法確保在創建的每個FeedClassExample實例上都會調用Dispose。最好的方法是避免創建一個FeedClassExample實例,如果在本ID下已經存在的話。否則,AddFeed方法應該處理它創建的任何FeedClassExample,但隨後決定不要存儲在字典中,或者與字典中的字符串交換(我不確定支持哪種方法)以及然後Dispose舊的。基本要求是,在AddFeed的實際執行之外的任何時候,字典將保存已創建但未銷燬的所有FeedClassExample實例。

在您的FeedClassExample類中添加析構函數可能會提供信息,該類除了記錄消息外什麼都不做。如果你正確地調用該類的Dispose,析構函數將永遠不會執行。如果您未能撥打Dispose,它會。因此,如果析構函數執行完畢,就可以知道你做錯了什麼。

+0

實際上,在ConcurrentDictionary中沒有添加... – digEmAll

+0

是的,這只是用於重現警告的示例代碼。如果密鑰存在,我的主代碼會在添加之前返回。 – BlueVoodoo

+0

@digEmAll:正確...使用'GetOrAdd'方法。 – Guffa