Streamwriter CA2202: не выбрасывайте объекты несколько раз
У меня есть кусок кода, который я использую при отладке, чтобы записать строку информации в файл.
private bool appendLine(string line2Write, string fileName)
{
try
{
StreamWriter tw;
using (tw = File.AppendText(fileName))
{
tw.WriteLine(line2Write);
tw.Close();
}
}
catch (Exception ex)
{
DialogResult result = MessageBox.Show("Unable to write to: " + fileName + "\r\n" + ex.ToString() + "\r\n OK to retry", "File Sysytem Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
if (result == DialogResult.Cancel)
{
return false;
}
}
return true;
}
Я не хочу оставлять файл открытым, потому что, если это отладочная информация, я не хочу рисковать последним битом в случае сбоя программы.
Я, вероятно, не понимаю, что CA2202 говорит мне.
Вот все утверждение об ошибке:
Предупреждение CA2202 Объект 'tw' может быть размещен более одного раза в методе 'familyFinances.appendLine(string, string)'. Чтобы избежать создания System.ObjectDisposedException, вы не должны вызывать Dispose более одного раза для объекта.
"tw" существует только в этом коде. И у меня никогда не было ошибки при запуске этого пути.
Варианты или предложения?
2 ответа
Ты звонишь Close
а также Dispose
, Ты звонишь Close
явно и Dispose
неявно через using
заявление. Два эквивалентны, у вас должен быть только один из них.
Это не выбросит предупреждение:
private bool appendLine(string line2Write, string fileName)
{
try
{
StreamWriter tw;
using (tw = File.AppendText(fileName))
{
tw.WriteLine(line2Write);
}
}
catch (Exception ex)
{
DialogResult result = MessageBox.Show("Unable to write to: " + fileName + "\r\n" + ex.ToString() + "\r\n OK to retry", "File Sysytem Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
if (result == DialogResult.Cancel)
{
return false;
}
}
return true;
}
В описании правила прямо говорится, что Close
а также Dispose
оба считаются
Реализация метода содержит пути кода, которые могут вызывать множественные вызовы System.IDisposable.Dispose или эквивалент Dispose, такой как метод Close() для некоторых типов, для одного и того же объекта.
Несмотря на то, что в этом случае объект не будет жаловаться на двойное удаление, нет реальной причины оставлять оба, поэтому это все еще хороший улов в отношении стиля кода.
Как уже упоминалось, эта проблема вызвана тем, что вы звоните Close()
внутри using
блок, и этот вызов должен быть удален. Я предлагаю вам покопаться и понять, почему эти звонки эквивалентны.
Посмотрите на StreamWriter.Close()
исходный код:
public override void Close() {
Dispose(true);
GC.SuppressFinalize(this);
}
И IDisposable.Dispose()
метод, который TextWriter
(база для StreamWriter
) реализует как показано ниже. это Dispose()
вызывается во время выполнения при закрытии фигурной скобки using
блок выполняется.
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
Компилятор переводит using
блок для try/finally
так что ваш код, о котором идет речь, эквивалентен:
StreamWriter tw = File.AppendText(fileName)
try {
tw.WriteLine(line2Write);
tw.Close();
}
finally {
tw.Dispose();
}
Таким образом, вы делаете одно и то же дважды, и таким образом получаете это предупреждение.
К вашему сведению - исходный код.NET Framework здесь