Streamwriter CA2202:不要多次处理对象
Streamwriter CA2202: Do not dispose objects multiple times
我在调试时使用一段代码将一行信息写入文件。
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" 只存在于这段代码中。而且,我从来没有用这种方式出错 运行。
选项或建议?
您调用 Close
和 Dispose
。您通过 using
语句显式调用 Close
并隐式调用 Dispose
。两者是等价的,你应该只有其中之一。
这不会引发警告:
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
都是considered
A method implementation contains code paths that could cause multiple calls to System.IDisposable.Dispose or a Dispose equivalent, such as a Close() method on some types, on the same object.
虽然在这种情况下对象不会抱怨双重处置,但没有真正的理由保留两者,所以它在代码风格方面仍然是一个很好的收获。
正如其他人已经提到的,这个问题是因为您在 using
块内调用 Close()
引起的,应该删除该调用。我建议你挖掘并理解为什么这些调用是等价的。
查看StreamWriter.Close()
源代码:
public override void Close() {
Dispose(true);
GC.SuppressFinalize(this);
}
以及 TextWriter
(StreamWriter
的基础)实现的 IDisposable.Dispose()
方法如下。 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 框架源代码 here
我在调试时使用一段代码将一行信息写入文件。
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" 只存在于这段代码中。而且,我从来没有用这种方式出错 运行。
选项或建议?
您调用 Close
和 Dispose
。您通过 using
语句显式调用 Close
并隐式调用 Dispose
。两者是等价的,你应该只有其中之一。
这不会引发警告:
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
都是considered
A method implementation contains code paths that could cause multiple calls to System.IDisposable.Dispose or a Dispose equivalent, such as a Close() method on some types, on the same object.
虽然在这种情况下对象不会抱怨双重处置,但没有真正的理由保留两者,所以它在代码风格方面仍然是一个很好的收获。
正如其他人已经提到的,这个问题是因为您在 using
块内调用 Close()
引起的,应该删除该调用。我建议你挖掘并理解为什么这些调用是等价的。
查看StreamWriter.Close()
源代码:
public override void Close() {
Dispose(true);
GC.SuppressFinalize(this);
}
以及 TextWriter
(StreamWriter
的基础)实现的 IDisposable.Dispose()
方法如下。 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 框架源代码 here