Streamwriter CA2202: не выбрасывайте объекты несколько раз - PullRequest
0 голосов
/ 04 октября 2018

У меня есть фрагмент кода, который я использую при отладке, чтобы записать строку информации в файл.

    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 ]

0 голосов
/ 04 октября 2018

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

Таким образом, вы делаете одно и то же дважды, и таким образом получаете это предупреждение.

FYI - исходный код .NET Framework здесь

0 голосов
/ 04 октября 2018

Звоните 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 () для некоторых типов, для одного и того же объекта.

Несмотря на то, что в этом случае объект не будет жаловаться на двойное удаление, нет никакой реальной причины оставлять оба, поэтому это все еще хороший улов в отношении стиля кода.

...