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 здесь

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