Как избавиться от объекта, который повторяется через его свойство Next? - PullRequest
2 голосов
/ 02 сентября 2010

У меня есть объект, который использует некоторые базовые собственные ресурсы и имеет указатель на следующий экземпляр, который я повторяю, как:

MyObject begin = null;

try
{
    begin = GetFirst();

    while (begin != null)
    {
        MyObject next = begin.Next();
        // do something with begin
        begin.Dispose();
        begin = next;
    }
}
finally
{    
    if (begin != null)
    {
        begin.Dispose();
    }
}

У меня проблема с анализом кода:

CA2202: Microsoft.Usage: Объект 'begin' может быть размещен более одного раза в методе 'x ()'. Чтобы избежать генерирования исключения System.ObjectDisposedException, не следует вызывать метод Dispose для объекта более одного раза.

Есть идеи, как избавиться от этой ошибки, не подавляя ее?

Ответы [ 3 ]

4 голосов
/ 02 сентября 2010

Мне, конечно, кажется, что ваш последний блок кода не нужен. Если begin != null, то ваш while цикл должен был продолжаться, нет?

ОБНОВЛЕНИЕ : Похоже, вы пытаетесь убедиться, что последнее полученное значение для begin удаляется в случае возникновения исключения. Попробуйте это:

MyObject begin = GetFirst();

while (begin != null)
{
    MyObject next;
    using (begin)
    {
        next = begin.Next();
        // do something with begin
    }

    begin = next;
}

Обратите внимание, что в приведенном выше предложении на самом деле может все же случиться, что вы в конечном итоге получите неразмещенный объект: последнее значение, присвоенное next, до конца блока using. Этот сценарий не был рассмотрен в вашем первоначальном вопросе, поэтому я не рассмотрел его в приведенном выше предложении. Это то, что следует учитывать, если это потенциальная проблема.

0 голосов
/ 02 сентября 2010

У вас, очевидно, есть какой-то механизм для идентификации первого элемента в цепочке, возможно, какой-то другой объект или некоторый статический элемент, который хранит первый элемент?

Как в вашем коде, который первоначально вызывает dispose:

GetFirst().Dispose();

Тогда единственная ответственность за метод dispose заключается в удалении текущего элемента и его потомков:

public void Dispose()
{
    if (Next() != null)
    {
        Next().Dispose();
    }
}

Это устраняет необходимость в цикле внутри метода dispose.Я бы также взглянул на шаблон dispose

0 голосов
/ 02 сентября 2010

Похоже, что Code Analysis считает возможным возникновение исключения во время метода Dispose().Если бы это было так, вы бы вошли в блок finally с уже расположенной, хотя и ненулевой ссылкой на begin.

Обратите внимание, что я бы предпочел этот подход только @ Dan, если вы планируетеобернуть вызов к begin.Dispose() в дополнительном перехвате и обработке ошибок.ИМО, решение Дэна более изящно.

Вот подход «попробуй наконец», который удаляет предупреждение:

MyObject begin = GetFirst();
MyObject next = null;

while (begin != null)
{
    try
    {
        next = begin.Next();
        // do something with begin
    }
    finally
    {
        begin.Dispose();
        begin = next;
    }
}
...