我的应用程序中有一个非常简单的日志记录机制,它定期将一行写入文件(一个日志库对我的需求来说太过分了)看起来像这样:
private string logfile = @"C:\whatever.log";
public void WriteLine(string line)
{
using(FileStream fs = File.Open(logfile, FileMode.Append))
{
// Log Stuff
}
}
因此,只要我调用该方法,就会在完成日志记录后创建并处理新的FileStream。所以我考虑使用已经实例化的对象来阻止连续创建新对象:
private string logfile = @"C:\whatever.log";
private FileStream myStream = File.Open(logfile, FileMode.Append);
public void WriteLine(string line)
{
using(myStream)
{
// Log Stuff
}
}
但是,the MSDN reference discourages this(最后一个例子),由于范围问题。 那个案子做了什么?我的第一个例子中的开销是否可以忽略不计?
答案 0 :(得分:3)
除了调用对象的using
方法之外,Dispose()
语句不做任何其他事情
因此,考虑到您的第二个示例,在第一次调用WriteLine(string)
方法后,文件流将被释放。因此,在第一个之后,对此方法的任何其他调用都将导致异常。
使用Chris在评论中建议的File.AppendText()
方法是一种方法。但请记住,使用此方法或任何其他File...
方法也会打开一个流并在之后关闭并处理它。
它只会减少代码。
答案 1 :(得分:2)
第二种方法也会在每次调用WriteLine
时处理流,因为您还使用using
语句。 MSDN不鼓励这种方法,因为即使对象被处置,变量myStream
仍然“存在”。所以这更容易出错。
如果您经常需要使用此方法,则应该使用using
“在外面”或使用try-catch-finally
:
var myLogger = new MyLogger();
try
{
// here is your app which calls myLogger.WriteLine(...) often
}
catch(Exception ex)
{
// log it
}
finally
{
myLogger.Dispose(); // myLogger is your Log class, dispose should call myStream.Dispose();
}
答案 2 :(得分:1)
开销可能不可忽视,但这可能不是重点。
当您使用using
时,创建,获取资源和处理已使用的资源的范围很大。你知道它的起始位置,使用位置以及它的完成位置。
如果你去第二个场景,你知道它的开始位置(它是在创建包含类的时候),但在那之后,你没有平台保证的方法来控制它的使用位置,以及在哪里(如果有的话)资源处理完毕。
如果这是关键代码,你自己可以做到这一点,并且你的包含类正确地实现IDisposable pattern,但这可能是棘手的,不适合胆小的人:)
但是,你在问题中说“一个日志库对我的需求来说太过分了”,所以我认为你的开销很小。恕我直言,您应该使用现成的File
方法之一,例如File.AppendAllText
:
public void WriteLine(string line)
{
//add an enter to the end
line += Environment.NewLine;
File.AppendAllText(logfile, line);
}
public void WriteLine(string line)
{
File.AppendAllLines(logfile, new []{line});
}