C# 如何正确处理此代码?

C# 如何正确处理此代码?,c#,dispose,idisposable,C#,Dispose,Idisposable,我有一个相当大的项目,我尽量保持干净整洁。当我在VisualStudio中运行代码分析器时,我发现了一个非常恼人的可靠性错误。我真的很想学习如何解决这个问题。下面是我正在做的一个简单例子 这是警告 警告1 CA2000:Microsoft。可靠性:在方法“MyExampleClassForStackOverflow.AddFeed(string)”中,在对象“new FeedClassExamle()”的所有引用都超出范围之前,对其调用System.IDisposable.Dispose 下面是

我有一个相当大的项目,我尽量保持干净整洁。当我在VisualStudio中运行代码分析器时,我发现了一个非常恼人的可靠性错误。我真的很想学习如何解决这个问题。下面是我正在做的一个简单例子

这是警告

警告1 CA2000:Microsoft。可靠性:在方法“MyExampleClassForStackOverflow.AddFeed(string)”中,在对象“new FeedClassExamle()”的所有引用都超出范围之前,对其调用System.IDisposable.Dispose

下面是我的示例代码:

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()
    {

    }
}

欢迎任何建议。

如果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());
}

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

从根本上说,需要对每个
AddFeed
方法进行处理,以确保在它创建的每个
FeedClassExample
实例上调用
Dispose
。最好的方法是避免创建一个
FeedClassExample
实例,如果该实例在当前ID下已经存在于dictionary中。否则,
AddFeed
方法应该处理它创建的任何
FeedClassExample
,然后决定不存储在字典中,或者与字典中的一个进行交换(我不确定
ConcurrentDictionary
支持什么方法来实现这一点),然后
Dispose
旧的。基本要求是,在实际执行
AddFeed
之外的任何时候,字典都将保存已创建但未销毁的
FeedClassExample
的所有实例


FeedClassExample
类中添加析构函数可能会提供一些信息,它除了记录消息之外什么都不做。如果在该类上正确调用
Dispose
,析构函数将永远不会执行。如果您未能调用
Dispose
,则它将执行此操作。因此,如果析构函数执行过,您就知道自己做错了。

我尝试过,但仍然得到:警告1 CA2000:Microsoft。可靠性:在方法“MyExampleClassForStackOverflow.AddFeed(string)”中,在对象“fce”的所有引用都超出范围之前,对其调用System.IDisposable.Dispose。如果执行
feed[id]=new FeedClassExamle(),是否会收到相同的消息?这似乎与
ConcurrentDictionary
类有关-当它被标准字典类替换时,消息消失。代码分析似乎没有意识到ConcurrentDictionary正在保留一个引用。@EugeneRyabtsev-是的,相同的警告。@BlueVoodoo:如果您确定正在执行的操作,您也可以取消该警告:是的,这只是复制警告的示例代码。如果键存在,我的主代码在添加之前返回。@DigeMail:对。。。使用
GetOrAdd
方法。问得好。在这种情况下,我总是抑制这种警告。。。知道是否有任何解决办法会很好是的,使用析构函数是个好主意。我可以这样做。关于在已有实例的情况下创建一个新实例,这在我的主代码中有介绍。在这里的简化示例中,我只是用它来演示如何重现警告。
if (!Feeds.ContainsKey(id)) {
  Feeds.GetOrAdd(id, new FeedClassExamle());
}