Почему я не могу избавиться от предупреждения CA2000? - PullRequest
2 голосов
/ 07 ноября 2011

Я пишу метод, который сбрасывает систему регистрации. Мне нужно получить экземпляр CsvFileLogWriter (пользовательский класс) и передать его в метод сброса. CsvFileLogWriter является одноразовым, поэтому я получаю предупреждение CA2000, скажите мне:

Warning 2   CA2000 : Microsoft.Reliability : In method 'Logger.InitializeCsvLogger
(string)', call System.IDisposable.Dispose on object 'tempWriter'
 before all references to it are out of scope.

Я выполнил инструкции, относящиеся к CA2000, и в результате получил следующий метод. Тем не менее, я все еще получаю предупреждение CA2000.

public static void InitializeCsvLogger(string path)
{
    ILogWriter tempWriter = null;

    try
    {
        tempWriter = new CsvFileLogWriter(path);
        ResetWriter(tempWriter);
        tempWriter = null;
    }
    finally
    {
        if (tempWriter != null)
            tempWriter.Dispose();
    }
}

Может кто-нибудь заметит мою ошибку?

EDIT

Я не хочу распоряжаться автором, на который ссылается tempWriter - это не временный объект, а просто временная ссылка. Я распоряжаюсь им только в случае сбоя в блоке try (поэтому tempWriter никогда не устанавливается равным нулю, а оператор if в блоке finally очищает ресурсы.) Я не хочу tempWriter удаление, если этот сбой не происходит - сам объект должен оставаться в использовании после установки в свойстве с помощью ResetWriter (tempWriter) . Это согласно правилам CA2000 - см. http://msdn.microsoft.com/en-us/library/ms182289.aspx?queryresult=true

Для ясности вот что ResetWriter делает - Writer является статическим свойством. Метод удаляет старого писателя и устанавливает нового.

private static void ResetWriter(ILogWriter newWriter)
{
    if (Writer != null)
        Writer.Dispose();
    Writer = newWriter;
}

EDIT

Я думаю, что SLaks заявил, что это ложный положительный результат. Если я возьму содержимое ResetWriter и вставлю его вместо вызова ResetWriter (по сути, изменив рефакторинг метода извлечения), CA2000 исчезнет.

Или, другими словами, следующее не выдает предупреждение CA2000:

public static void InitializeCsvLogger(string path)
{
    ILogWriter tempWriter = null;

    try
    {
        tempWriter = new CsvFileLogWriter(path);
        if (Writer != null)
            Writer.Dispose();
        Writer = tempWriter;
        tempWriter = null;
    }
    finally
    {
        if (tempWriter != null)
            tempWriter.Dispose();
    }
}

Ответы [ 3 ]

3 голосов
/ 07 ноября 2011

Когда вы присваиваете null для tempWriter:

tempWriter = null;

tempWriter больше не ссылается на созданный вами объект.Следовательно, вы не можете избавиться от объекта.

В этом случае вам действительно следует использовать блок using:

using(var tempWriter = new CsvFileLogWriter(path))
{
    ResetWriter(tempWriter);
}

Делая это, вам больше не нужно беспокоиться овызов Dispose (или установка ссылки на ноль).

2 голосов
/ 07 ноября 2011

Это предупреждение является ложным срабатыванием.

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

Вы должны подавить предупреждение.

2 голосов
/ 07 ноября 2011

Написав tempWriter = null, вы предотвращаете его удаление, поскольку блок finally запускается только после этого.

Вместо этого вы должны использовать оператор using.

Этот ответ правильный, но противоречит вашим реальным намерениям .

...