Почему я не могу избавиться от предупреждения CA2000?

Я пишу метод, который сбрасывает систему регистрации. Мне нужно получить экземпляр 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();
    }
}

Может кто-нибудь, пожалуйста, определите мою ошибку?

РЕДАКТИРОВАТЬ

Я не хочу распоряжаться автором, на который ссылается tempWriter - это не временный объект, а просто временная ссылка. Я распоряжаюсь им только в случае сбоя в блоке try (таким образом, для tempWriter никогда не устанавливается значение null, а оператор 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;
}

РЕДАКТИРОВАТЬ

Я думаю, как 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 ответа

Решение

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

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

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

Когда вы назначаете null в tempWriter:

tempWriter = null;

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

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

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

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

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

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

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

Другие вопросы по тегам