转让所有权后如何摆脱CA2000警告?

以下代码生成两个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 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方法。

处置相同的范围不是一种选择。

您想修复代码还是只是禁止警告? 抑制警告很简单:

 [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Your reasons go here")] public void Initialize() { // ... } 

我也在connect.microsoft.com上问了这个,这就是他们回答的问题:

您可以通过使添加一次性对象的容器/集合对象实现ICollection或ICollection 来解决此问题。 执行Add的方法也必须具有以“Add”开头的名称。

当然,当类Test实现ICollection 时,警告就会消失。 对于相关案例,这是一个可接受的解决方案。 但是,如果不适合实施ICollection以表明所有权转让,那么这仍然是一个悬而未决的问题。

 public sealed class Test: IDisposable, ICollection { public void Initialize() { var item1 = new Item(); // no warning itemCollection.Add(item1); var item2 = new Item(); // no warning ((ICollection)this).Add(item2); var item3 = new Item(); // no warning AddSomething(item3); } //... implement ICollection and Method AddSomething } 

我知道这是示例代码,因此这种解决方法是否适用于您的实际代码,我不能说。

在这种特殊情况下,如果将对象创建代码移动到它自己的方法中,返回新的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的类极不可能正确处理包含的对象。

当然,首先要做的是实际让Dispose方法清理集合的成员。 我假设这只是示例中的错误,而不是真正的代码。

除此之外,我会压制警告。 我坚决认为任何压制:

  1. 应该是一个非常短的范围,所以它不会抑制另一个警告的情况,这是一个真正的错误。
  2. 应该注释注释,无论多么明显的脑死亡,似乎警告是安全的压制。

也就是说,我认为对CA2000的分析是如此之差,以至于不值得在默认情况下进行检查,但仅限于偶尔的评论。 在一定数量的误报后,警告甚至不能被视为警告,只是噪音隐藏了真正的警告,因此使代码更容易出错。