Streamwriter CA2202:请勿多次放置对象

时间:2018-10-04 15:56:36

标签: c# streamwriter idisposable 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在方法'familyFinances.appendLine(string,string)'中可以多次放置对象'tw'。为避免生成System.ObjectDisposedException,不应在一个对象上多次调用Dispose。

“ tw”仅存在于此代码中。而且,我从来没有遇到过这样的错误。

选项或建议?

2 个答案:

答案 0 :(得分:2)

您呼叫CloseDispose。您通过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;
}

规则描述明确指出CloseDispose均为considered

  

方法实现包含可能导致对同一对象上的System.IDisposable.Dispose或Dispose等效项的多次调用的代码路径,例如某些类型的Close()方法。

尽管在这种情况下对象不会抱怨双重处置,但没有真正的理由要保留两者,因此在代码风格方面仍然是一个不错的选择。

答案 1 :(得分:1)

正如其他人已经提到的,此问题是由于您在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框架源代码here