如何正确处理此代码

本文关键字:代码 正确处理 | 更新日期: 2023-09-27 18:34:48

我有一个相当大的项目,我尽量保持干净整洁。当我在Visual Studio中运行代码分析器时,我收到一个可靠性错误,我觉得这很烦人。我真的很想学习如何解决它。这是我正在做的事情的一个简化示例。

这是警告。

警告 1 CA2000:Microsoft.可靠性:在方法"MyExampleClassForStackOverflow.AddFeed(string("中,在对象"new FeedClassExamle(("上调用 System.IDisposable.Dispose 在对象 'new 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())
{
}

欢迎任何建议。

如何正确处理此代码

存在警告是因为代码分析工具无法确定对象是否会正确释放。 按照编写代码的方式,对象实际上不会正确释放,但修复代码可能不会消除警告。

从根本上说,需要发生的是针对每个AddFeed方法,以确保某些东西将在它创建的每个FeedClassExample实例上调用Dispose。 最好的方法是避免创建FeedClassExample实例(如果字典中已存在当前 ID 下的实例(。 如果做不到这一点,AddFeed 方法应该要么处理它创建的任何FeedClassExample,但随后决定不存储在字典中,要么与字典中的那个交换(我不确定ConcurrentDictionary支持什么方法来做到这一点(,然后Dispose旧的。 基本要求是,在实际执行AddFeed之外的任何时候,字典将包含所有已创建但未销毁的FeedClassExample实例。

FeedClassExample 类中添加析构函数可能会提供任何信息,该析构函数除了记录消息外什么都不做。 如果正确调用该类的Dispose,则析构函数将永远不会执行。 如果您无法调用Dispose,它会。 因此,如果析构函数执行,你可以知道你做错了什么。

如果 TryAdd 失败,对象不会被释放,因此请尝试显式执行此操作:

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

仅在需要添加实例时才创建实例:

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