Question

I have a very simple logging mechanism in my application which periodically writes a line to a file (a logging library would be overkill for my needs) which looks something like this:

private string logfile = @"C:\whatever.log";

public void WriteLine(string line)
{
   using(FileStream fs = File.Open(logfile, FileMode.Append))
   {
    // Log Stuff
   }
}

So any time I call that method, a new FileStream is created and disposed after logging is finished. So I considered using an already instantiated object to prevent the continuous creation of new objects:

private string logfile = @"C:\whatever.log";
private FileStream myStream = File.Open(logfile, FileMode.Append);

public void WriteLine(string line)
{
   using(myStream)
   {
    // Log Stuff
   }
}

However, the MSDN reference discourages this (last example), due to scope issues. What does one do in that case? Is the overhead in my first example negligible?

Was it helpful?

Solution

The using statement doesn't do anything else than calling the Dispose() method of the object.
So considering your second example, after the first call to the WriteLine(string) method the filestream is disposed. So any other call, after the first one, to this Method will result in an exception.

Using the File.AppendText() method like Chris had suggested in the comment would be a way to go. But keep in mind, that using this or any other File... method will also open a stream and close and dispose it afterwards.
It will just result in less code.

OTHER TIPS

The second approach does also dispose the stream every time you call WriteLine since you are also using the using-statement. MSDN discourages from this approach because the variable myStream does still "exist" even if the object is disposed. So that is more error-prone.

If you often need to use this method you should cosider to use the using "outside" or use a 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();
}

The overhead might not be negligible, but that might be beside the point.

When you are using using, the creation, acquisition of resource and the disposing of the used resources is nicely scoped. You know where it starts, where it's used, and where it's finished.

If you go for the second scenario, you know where it starts (it's when the containing class is created), but after that, you have no platform-guaranteed way to control where it's used, and where (if at all) the resources are disposed.

You can do this yourself if this is critical code, and your containing class implements the IDisposable pattern properly, but this can be tricky and not for the faint of heart :)

However, you stated in the question "a logging library would be overkill for my needs", so I think you are fine with the minimal overhead. IMHO, you should be fine with one of the ready-made File methods, like File.AppendAllText:

public void WriteLine(string line)
{
   //add an enter to the end
   line += Environment.NewLine;
   File.AppendAllText(logfile, line);
}

or File.AppendAllLines:

public void WriteLine(string line)
{
   File.AppendAllLines(logfile, new []{line});
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top