Почему я не могу избавиться от предупреждения 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
утверждение вместо.
Этот ответ правильный, но противоречит вашим реальным намерениям.