Как избавиться от предупреждения CA2000 при переходе права собственности? - PullRequest
15 голосов
/ 14 октября 2010

Следующий код генерирует два предупреждения 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 не генерируется предупреждение. Похоже, Code Analysis предполагает, что ICollection возьмет на себя ответственность за предмет и в конечном итоге избавится от него.

Есть ли способ пометить мои Add методы, чтобы предупреждение исчезло?

Я ищу что-то похожее на ValidatedNotNullAttribute для CA1062.

Редактировать: чтобы было понятно: это не мой настоящий код. В реальном коде все правильно расположено.

Просто CA не распознает, что вызов моих Add методов передает право собственности. Я бы хотел, чтобы мои методы Add обрабатывались так же, как ICollection.Add.

Утилизация в одной и той же области не возможна.

Ответы [ 4 ]

10 голосов
/ 14 октября 2010

Хотите исправить код или просто отключить предупреждения?Подавить предупреждения просто:

[SuppressMessage("Microsoft.Reliability",
                 "CA2000:DisposeObjectsBeforeLosingScope",
                 Justification = "Your reasons go here")]
public void Initialize()
{
    // ...
}
8 голосов
/ 18 октября 2010

Я знаю, что это пример кода, и поэтому будет ли этот обход работать в вашем реальном коде, я не могу сказать.

В этом конкретном случае, если вы перемещаете код создания объекта в его собственный метод, который возвращает новый Item, тогда предупреждение исчезнет, ​​например, change:

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.

Edit

Увидев ответ Хенрика и ответ по Connect, все, что я могу сказать, это bletch .Нет никакой гарантии, что реализация ICollection также реализует IDisposable, и хотя его опубликованный пример действительно реализует IDisposable, очевидно, это не требуется, чтобы затормозить анализ кода (я был бы несколько в порядке, если бы вам пришлось реализовать оба).Класс, реализующий ICollection, но не реализующий IDisposable, вряд ли будет иметь дело с правильным удалением содержащихся объектов.

7 голосов
/ 19 октября 2010

Я также спросил это на connect.microsoft.com, и вот что они ответили:

Вы можете обойти проблему, имея контейнер / объект сбора, который добавляет одноразовый объект, реализующий ICollection или ICollection . Метод, который выполняет добавление, также должен иметь имя, начинающееся с «Добавить».

И, конечно же, когда класс Test реализует ICollection , предупреждение исчезает. Это приемлемое решение для рассматриваемого случая. Но все еще остается открытым вопрос, что делать, когда нецелесообразно внедрять 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
}
1 голос
/ 14 октября 2010

Ну, конечно, первое, что нужно сделать, - это применить метод Dispose для очистки членов коллекции.Я предполагаю, что это просто ошибка в примере, а не реальный код.

Помимо этого, я бы просто подавил предупреждение.Я очень твердо убежден в том, что любое подавление:

  1. должно иметь очень короткую область, поэтому оно не исключает другой случай предупреждения, которое является подлинной ошибкой.с комментариями, независимо от того, насколько очевиден мозг, кажется, что предупреждение безопасно подавить.

Тем не менее, я думаю, что анализ CA2000 настолько плох, что не стоит проверять его по умолчанию, но только в периодических обзорах.После определенного количества ложных срабатываний предупреждение уже нельзя считать предупреждением, просто шум, который скрывает реальные предупреждения и, следовательно, повышает вероятность ошибок в коде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...