以下代码生成两个CA2000警告(除其他外,但这不是重点)。
public sealed class Item: IDisposable
{
public void Dispose() {}
}
public sealed class ItemContainer
{
public void Add(Item item)
{
}
}
public sealed class Test: IDisposable
{
private ICollection<Item> itemCollection;
private ItemContainer itemContainer;
private void Add(Item item)
{
itemCollection.Add(item);
}
public void Initialize()
{
var item1 = new Item(); // no warning
itemCollection.Add(item1);
var item2 = new Item(); // CA2000: call Dispose on object item2
Add(item2);
var item3 = new Item(); // CA2000: call Dispose on object item3
itemContainer.Add(item3);
}
public void Dispose() {}
}
请注意,item1没有生成警告。似乎,代码分析假设ICollection
将负责该项目并最终处置它。
有没有办法标记我的Add
方法,以便警告消失?
我正在为CA1062寻找类似于ValidatedNotNullAttribute
的东西。
编辑:说清楚:这不是我真正的代码。在真实的代码中,一切都妥善处理。
只是CA无法识别对Add
方法的调用会转移所有权。
我希望它以与处理ICollection.Add
相同的方式处理我的Add方法。
在同一范围内处置不是一种选择。
答案 0 :(得分:10)
您想要修复代码还是只是禁止警告?抑制警告很简单:
[SuppressMessage("Microsoft.Reliability",
"CA2000:DisposeObjectsBeforeLosingScope",
Justification = "Your reasons go here")]
public void Initialize()
{
// ...
}
答案 1 :(得分:7)
我知道这是示例代码,因此这种解决方法是否适用于您的实际代码,我不能说。
在这种特殊情况下,如果您将对象创建代码移动到它自己的方法中,它返回新的Item,那么警告将消失,例如改变:
public void Initialize()
{
var item1 = new Item(); // no warning
itemCollection.Add(item1);
var item2 = CreateItem(); // CA2000 no longer appears
Add(item2);
var item3 = new Item(); // CA2000: call Dispose on object item3
itemContainer.Add(item3);
}
private Item CreateItem()
{
return new Item();
}
显然,CreateItem方法可以传递任意参数传递给Item构造函数。
修改的
看过Henrik的回答,以及对Connect的回复,我只能说是 bletch 。不能保证ICollection实现也实现了IDisposable,虽然他发布的示例确实实现了IDisposable,但显然不需要关闭代码分析(如果你必须同时实现两者,我会有所帮助)。实现ICollection但未实现IDisposable的类极不可能正确处理包含的对象。
答案 2 :(得分:7)
我也在connect.microsoft.com上问了这个问题,这就是他们的回答:
您可以通过使添加一次性对象的容器/集合对象实现ICollection或ICollection&lt; T&gt;来解决该问题。执行添加的方法也必须具有以“添加”开头的名称。
当然,当类Test实现ICollection&lt; Item&gt;时,警告就会消失。对于相关案例,这是一个可接受的解决方案。但是,如果不适合实施ICollection以表明所有权转移,那么仍然是一个悬而未决的问题。
public sealed class Test: IDisposable, ICollection<Item>
{
public void Initialize()
{
var item1 = new Item(); // no warning
itemCollection.Add(item1);
var item2 = new Item(); // no warning
((ICollection<Item>)this).Add(item2);
var item3 = new Item(); // no warning
AddSomething(item3);
}
//... implement ICollection and Method AddSomething
}
答案 3 :(得分:1)
当然,首先要做的是让Dispose方法实际上清理集合的成员。我假设这只是示例中的错误,而不是真正的代码。
除此之外,我会压制警告。我强烈坚持任何压制:
那就是说,我认为对CA2000的分析是如此之差,以至于不值得在默认情况下进行检查,但仅限于偶尔的评论。在一定数量的误报之后,警告甚至不能再被视为警告,只是隐藏真实警告的噪音,从而使代码更容易出错。