The following code generates two CA2000 warnings (among others, but that's not the point).
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() {}
}
Note that there is no warning generated for item1. It seems, Code Analysis assumes the ICollection
will take responsibility of the item and eventually dispose it.
Is there a way to mark my Add
methods, so that the warning goes away?
I'm looking for something similar to ValidatedNotNullAttribute
for CA1062.
Edit: to make it clear: this is not my real code. In the real code, everything is properly disposed.
It's just that CA does not recognize that the call to my Add
methods transfers ownership.
I would like it to treat my Add methods in the same way it treats ICollection.Add
.
Disposing in the same scope is not an option.
Do you want to fix the code or just suppress the warnings? Suppressing the warnings is straightforward:
[SuppressMessage("Microsoft.Reliability",
"CA2000:DisposeObjectsBeforeLosingScope",
Justification = "Your reasons go here")]
public void Initialize()
{
// ...
}
I also asked this at connect.microsoft.com and this is what they answered:
You can workaround the issue by having the container/collection object that adds the disposable object implement ICollection or ICollection<T>. The method that performs the Add must also have name starting with "Add".
And sure enough: when class Test implements ICollection<Item>, then the warning goes away. This is an acceptable solution for the case in question. But it's still an open question what to do, when it's not appropriate to implement ICollection to indicate transfer of ownership.
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With