[英]CA2000 Dispose warning when reference held in a ConcurrentDictionary
I have a parent class that has a collection of child classes.我有一个包含子类集合的父类。 Both classes are
IDisposable
.这两个类都是
IDisposable
。 I am receiving warning CA2000 ("Call Dispose on object ... before all references to it are out of scope."), but I don't want to Dispose()
it in the same method call it's created, as the child has a long lifetime.我收到警告CA2000 (“在对象上调用 Dispose ......在对它的所有引用超出范围之前。”),但我不想在它创建的相同方法调用中
Dispose()
它,因为孩子有漫长的一生。 I'm keeping a reference to it in the parent class.我在父类中保留对它的引用。 If that reference is in a
Dictionary
or a ConcurrentBag
, all is well.如果该引用在
Dictionary
或ConcurrentBag
,则一切正常。 If the reference is in a ConcurrentDictionary
, CA2000 is listed.如果引用在
ConcurrentDictionary
,则列出CA2000 。
As far as I can tell I'm implementing IDisposable
correctly.据我所知,我正在正确实施
IDisposable
。 Perhaps the way I'm iterating a concurrent collection and calling Dispose()
could be improved, although I suspect that's not the source of the warning.也许我迭代并发集合和调用
Dispose()
可以改进,尽管我怀疑这不是警告的来源。
Is this a bug in the compiler/warnings, or can I achieve compliance through code?这是编译器/警告中的错误,还是我可以通过代码实现合规性? My stab at a theory is that it's being of the function syntax used to add the reference, but I'm not sure.
我的一个理论是它是用于添加引用的函数语法,但我不确定。
The following example reproduces the warning, with child1
and child3
being fine, but child2
producing the warning, when the only difference is the container type:下面的示例再现警告,与
child1
和child3
感很好,但child2
产生警告,当唯一的区别是,容器类型:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
public class ParentDisposable : IDisposable
{
private readonly Dictionary<string, ChildDisposable> dictionary = new Dictionary<string, ChildDisposable>();
private readonly ConcurrentDictionary<string, ChildDisposable> concurrentDictionary = new ConcurrentDictionary<string, ChildDisposable>();
private readonly ConcurrentBag<ChildDisposable> concurrentBag = new ConcurrentBag<ChildDisposable>();
public void CreateChild()
{
// I want to create these disposable children, use them beyond the lifetime of this method call, and dispose of them when this parent class is disposed of
var child1 = new ChildDisposable(); // No warning
var child2 = new ChildDisposable(); // Warning CA2000 Call System.IDisposable.Dispose on object created by 'new ChildDisposable()' before all references to it are out of scope.
var child3 = new ChildDisposable(); // No Warning
this.dictionary.Add("key", child1);
this.concurrentDictionary.AddOrUpdate("key", child2, (k, v) => child2);
this.concurrentBag.Add(child3);
}
#region IDisposable Pattern
private bool disposedValue = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposedValue)
{
if (disposing)
{
foreach (var key in this.dictionary.Keys)
{
this.dictionary[key].Dispose();
}
foreach (var key in this.concurrentDictionary.Keys)
{
this.concurrentDictionary[key].Dispose();
}
foreach (var child in this.concurrentBag)
{
child.Dispose();
}
}
this.disposedValue = true;
}
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
#endregion IDisposable Pattern
}
public class ChildDisposable : IDisposable
{
private EventWaitHandle waitObject = new EventWaitHandle(false, EventResetMode.AutoReset);
#region IDisposable Pattern
private bool disposedValue = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposedValue)
{
this.waitObject.Dispose();
this.disposedValue = true;
}
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
#endregion IDisposable Pattern
}
This is not a problem in your code, it's an oversight in the version of FxCop you are using.这不是您代码中的问题,而是您使用的 FxCop 版本的疏忽。
This has been fixed in the latest version.这已在最新版本中修复。 See https://github.com/dotnet/roslyn-analyzers/issues/3082
见https://github.com/dotnet/roslyn-analyzers/issues/3082
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.