2012-05-20 5 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

Предупреждение существует потому что инструменты анализа кода не могут определить, будет ли объект правильно настроен. То, как написан ваш код, на самом деле объект не будет правильно настроен, но исправление кода, скорее всего, не устранит предупреждение.

По существу, что должно произойти для каждого метода AddFeed, чтобы гарантировать, что что-то вызовет Dispose на каждый созданный экземпляр FeedClassExample. Наилучший подход заключается в том, чтобы избежать создания экземпляра FeedClassExample, если он уже существует в подписях под настоящим идентификатором. В противном случае метод AddFeed должен либо уничтожить любой созданный FeedClassExample, но затем решает не хранить в словаре, а также менять его с помощью словаря (я не уверен, какие методы поддерживают ConcurrentDictionary) и затем Dispose старый. Существенным требованием является то, что во всех случаях вне фактического исполнения AddFeed словарь будет содержать все экземпляры FeedClassExample, которые были созданы, но не уничтожены.

Может быть информативным добавить деструктор в ваш класс FeedClassExample, который ничего не делает, кроме журнала. Если вы правильно вызываете Dispose в этом классе, деструктор никогда не будет выполняться. Если вы не позвоните по телефону Dispose, он будет. Таким образом, если деструктор когда-либо выполняется, вы можете знать, что делаете что-то неправильно.

+0

Да, хорошая идея с деструктором. Я могу это сделать. Что касается создания нового экземпляра, если он уже существует, который описан в моем основном коде. Просто отсутствует в упрощенном примере здесь, который я только что использовал, чтобы продемонстрировать, как воспроизвести предупреждение. – BlueVoodoo

1

Объект не получает удалялись, если TryAdd не удается, поэтому старайтесь делать это в явном виде:

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

я попробовал, но все еще получаю: Предупреждения \t \t 1 CA2000: Microsoft.Reliability: В методе «MyExampleClassForStackOverflow.AddFeed (строка) ', вызовите System.IDisposable.Dispose на объекте' fce ', прежде чем все ссылки на него выйдут из области видимости. – BlueVoodoo

+0

Получаете ли вы одно и то же сообщение, если вы делаете 'Feeds [id] = new FeedClassExamle();'? –

+0

Это похоже на класс 'ConcurrentDictionary' - сообщение исчезает, когда оно заменяется стандартным классом словаря.Похоже, анализ кода не понимает, что ConcurrentDictionary сохраняет ссылку. – Richard

0

только создать экземпляр, если он должен быть добавлен:

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

На самом деле нет Добавить в ConcurrentDictionary ... – digEmAll

+0

Да, это всего лишь пример кода для воспроизведения предупреждения. Мой основной код возвращается перед добавлением, если ключ существует. – BlueVoodoo

+0

@digEmAll: Right ... Используйте метод GetOrAdd. – Guffa

Смежные вопросы