C# - nested using statements redundant? - c#

I came across the following example code in the MSDN documentation, demonstrating the use of the System.IO.StreamReader class to read UTF-8 text from a System.IO.FileStream object. The two nested using statements struck me as redundant - surely calling Dispose() on one of the objects does the trick, and properly releases the file handle? (Source: http://msdn.microsoft.com/en-us/library/yhfzs7at.aspx)
using (FileStream fs = new FileStream(path, FileMode.Open))
{
using (StreamReader sr = new StreamReader(fs))
{
while (sr.Peek() >= 0)
{
Console.WriteLine(sr.ReadLine());
}
}
}
Would it not be simpler, and equally correct, to rewrite that code in the following way?
using (FileStream fs = new FileStream(path, FileMode.Open))
{
StreamReader sr = new StreamReader(fs);
while (sr.Peek() >= 0)
{
Console.WriteLine(sr.ReadLine());
}
}

According to the documentation, The StreamReader object calls Dispose() on the provided Stream object when StreamReader.Dispose is called. This means using the StreamReader guarantees disposal of the underlying Stream. It does not hold vice versa: disposing only the Stream does not suffice - the StreamReader may be allocating other native resources. So the second sample is not correct.
(using only the StreamReader does not cover the case that the StreamReader constructor can throw. To cover this case, both using's would be needed. Since it only throws for non-readable or null streams, this may not be relevant though.)
In general, you should always dispose on every disposable object. It is part of the IDisposable contract that it does not hurt to dispose an object multiple times, and the overhead of doing so is low.

The second sample is simply wrong on principle.
It won't leak anything but that relies on the knowledge that a StreamReader has no resources of its own and does not actually needs Disposing even though it is IDisposable.
A single using(){} around the StreamReader would have been more or less correct here, based on the documented (and criticized) feature that the Reader will close its Stream.
The best practice here is to use 2 using statments. Note that they are very cheap, and you simply want code that's consistent.

Related

Stream management after Environment.exit() invocation

I was searching in StackOverflow about try-finally and using blocks and what are the best practices on using them.
I read in a comment here that if your application is terminated abruptly by killing the process, a finally block will not get executed.
I was wondering, does the same apply to the using blocks? Will for example a stream get closed if a Environment.exit() call occurs inside the using block?:
//....
using (FileStream fsSource1 = new FileStream(pathSource,
FileMode.Open, FileAccess.Read))
{
//Use the stream here
Environment.exit();
}
As a second thought on it, and knowing that CLR Garbage Collector will probably take care of the stream objects if not closed properly in the program calls, is it considered necessary to close a stream in code, if the program gets terminated for sure after the completion of the stream usage?
For example, is there any practical difference between:
//....
using (FileStream fsSource1 = new FileStream(pathSource,
FileMode.Open, FileAccess.Read))
{
//Use the stream here
}
Environment.exit();
And:
//....
FileStream fsSource1 = new FileStream(pathSource, FileMode.Open, FileAccess.Read);
//Use the stream here
Environment.exit();
Or even the example mentioned before?
It shouldn't make a difference in the specific case of FileStream, modulo a tricky corner case when you used its BeginWrite() method. Its finalizer attempts to complete writing any unwritten data still present in its internal buffer. This is however not generally true, it will make a difference if you use StreamWriter for example.
What you are leaving up to the .NET Framework to decide is whether you truly meant to jerk the floor mat and seize writing the file. Or whether it should make a last-gasp attempt to flush any unwritten data. The outcome in the case of StreamWriter will tend to be an unpleasant one, non-zero odds that something is going to fall over when it tries to read a half-written file.
Always be explicit, if you want to make sure this does not happen then it is up to you to ensure that you properly called the Close() or Dispose() method. Or delete the file.

Repeatedly reading small file throws OutOfMemory

I have two programs that work together. To coordinate their operations I use a small settings file. This setting file contains two words separated by a ';'. So in the one program I repeatedly read the words in the file using a while loop. By repeatedly I mean once every second. The loop only terminates when the program terminates; when the user turns off the pc.
But with each iteration of the loop the program size in memory increases until the program throws an OutOfMemory exception. I have tried two different methods of reading the files but both causes the program to 'grow' in memory.
FileStream FS = new FileStream("br.stat", FileMode.Open);
StreamReader SR = new StreamReader(FS);
string s = SR.ReadToEnd();
FS.Dispose();
SR.Dispose();
and
string S = File.ReadAllText("br.stat");
Is there a way to read a file repeatedly with out this happening?
Thanks.
the problem is the design, more so than the implementation. You only need to read from the file once when the app starts and again when the file changes. You can use FileSystemWatcher to detect changes to the file and reload the settings.
This uses drastically less resources than reading the file indefinitely.
also, you'll want to take advantage of the using keyword to ensure you properly dispose of the file stream and reader. In fact I would simplify and just use File.ReadAllText(filename).
I think you're doing it wrong. Realistically there is no need to read the file every iteration unless its changed.
Instead it would be better to use a FileSystemWatcher http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.changed(v=vs.85).aspx to read the values and change your control values.
You should also use the following to circumvent your memory leak issues
using (var FS = new FileStream("br.stat", FileMode.Open))
{
using (var SR = new StreamReader(FS))
{
var s = SR.ReadToEnd();
}
}
I would recomend you look at using an using statement
File and Font are examples of managed types that access unmanaged
resources (in this case file handles and device contexts). There are
many other kinds of unmanaged resources and class library types that
encapsulate them. All such types must implement the IDisposable
interface.
As a rule, when you use an IDisposable object, you should declare and
instantiate it in a using statement. The using statement calls the
Dispose method on the object in the correct way, and (when you use it
as shown earlier) it also causes the object itself to go out of scope
as soon as Dispose is called. Within the using block, the object is
read-only and cannot be modified or reassigned.
so something like
using (FileStream FS = new FileStream("br.stat", FileMode.Open))
using (StreamReader SR = new StreamReader(FS))
{
string s = SR.ReadToEnd();
}

Writing to txt file with StreamWriter and FileStream

I ran into something interesting when using a StreamWriter with a FileStream to append text to an existing file in .NET 4.5 (haven't tried any older frameworks). I tried two ways, one worked and one didn't. I'm wondering what the difference between the two is.
Both methods contained the following code at the top
if (!File.Exists(filepath))
using (File.Create(filepath));
I have the creation in a using statement because I've found through personal experience that it's the best way to ensure that the application fully closes the file.
Non-Working Method:
using (FileStream f = new FileStream(filepath, FileMode.Append,FileAccess.Write))
(new StreamWriter(f)).WriteLine("somestring");
With this method nothing ends up being appended to the file.
Working Method:
using (FileStream f = new FileStream(filepath, FileMode.Append,FileAccess.Write))
using (StreamWriter s = new StreamWriter(f))
s.WriteLine("somestring");
I've done a bit of Googling, without quite knowing what to search for, and haven't found anything informative. So, why is it that the anonymous StreamWriter fails where the (non-anonymous? named?) StreamWriter works?
It sounds like you did not flush the stream.
http://msdn.microsoft.com/en-us/library/system.io.stream.flush.aspx
It looks like StreamWriter writes to a buffer before writing to the final destination, in this case, the file. You may also be able to set the AutoFlush property and not have to explicitly flush it.
http://msdn.microsoft.com/en-us/library/system.io.streamwriter.autoflush.aspx
To answer your question, when you use the "using" block, it calls dispose on the StreamWriter, which must in turn call Flush.
The difference between the two code snippets is the use of using. The using statement disposes the object at the end of the block.
A StreamWriter buffers data before writing it to the underlying stream. Disposing the StreamWriter flushes the buffer. If you don't flush the buffer, nothing gets written.
From MSDN:
You must call Close to ensure that all data is correctly written out to the underlying stream.
See also: When should I use “using” blocks in C#?

Reusing a stream after a method has completed

I am currently working on a C# project that uses a FileStream to open a file and passes the information to a StreamReader for it to be processed.
What I want to be able to do is I have a method which passes the stream to another method, that does the processing and once that method finishes, the original method calls another method passing it the same stream. However, when the first stream process completes when the second method is called it displays an exception saying that the thread is not readable.
When I look at debugging the stream, when I look at the details about the stream it says that it cannot be read, seek or write, and the length parameter of the stream says threw an exception of type System.ObjectDisposedException.
The question is, how can I keep the stream readable after the first method has completed so that the same stream can be processed in the second stream.
Thanks for any help you can provide.
if your streamReader is part of "using" statement, it disposes the file stream in the end of the statement block.
using (StreamReader reader = new StreamReader(fileStream))
{
..
}
Simple solution is not to dispose the reader explicitly, leaving it to GC
[More thoughts]
If most of the methods are accessing file stream through TextReader interface, you can pass reader thus avoiding the problem with the ownership.
If I understood you correctly, your stream is getting closed too fast. Based on what you say, it might be because you are Closing or Disposing StreamReader which, according to documentation, will close underlying stream.
Try not closing StreamReader (just ignore it, after it's not needed).
For example, if your code looks like this:
void P()
{
var stream = new FileStream();
P1(stream);
P2(stream);
}
void P1(FileStream stream)
{
using (var reader = new StreamReader(stream))
{
......
} //Here you would have disposed StreamReader and close FileStream
}
void P2(FileStream stream) // Stream is already closed
{
}
You have closed your stream in 1st method. You will have the same problem if you call:
reader.Dispose();
reader.Close();
stream.Dispose();
stream.Close();
using (stream);
So make sure aren't doing any of those things.
Btw: in C#5 I have heard, that Readers/Writers will be parametrized, if you want then to close underlying stream when they are closed (just like CryptoStream have right now)

Is it necessary to wrap StreamWriter in a using block?

A few days ago I posted some code like this:
StreamWriter writer = new StreamWriter(Response.OutputStream);
writer.WriteLine("col1,col2,col3");
writer.WriteLine("1,2,3");
writer.Close();
Response.End();
I was told that instead I should wrap StreamWriter in a using block in case of exceptions. Such a change would make it look like this:
using(StreamWriter writer = new StreamWriter(Response.OutputStream))
{
writer.WriteLine("col1,col2,col3");
writer.WriteLine("1,2,3");
writer.Close(); //not necessary I think... end of using block should close writer
}
Response.End();
I am not sure why this is a valuable change. If an exception occurred without the using block, the writer and response would still be cleaned up, right? What does the using block gain me?
Nope the stream would stay open in the first example, since the error would negate the closing of it.
The using operator forces the calling of Dispose() which is supposed to clean the object up and close all open connections when it exits the block.
I'm going to give the dissenting opinion. The answer to the specific question "Is it necessary to wrap StreamWriter in a using block?" is actually No. In fact, you should not call Dispose on a StreamWriter, because its Dispose is badly designed and does the wrong thing.
The problem with StreamWriter is that, when you Dispose it, it Disposes the underlying stream. If you created the StreamWriter with a filename, and it created its own FileStream internally, then this behavior would be totally appropriate. But if, as here, you created the StreamWriter with an existing stream, then this behavior is absolutely The Wrong Thing(tm). But it does it anyway.
Code like this won't work:
var stream = new MemoryStream();
using (var writer = new StreamWriter(stream)) { ... }
stream.Position = 0;
using (var reader = new StreamReader(stream)) { ... }
because when the StreamWriter's using block Disposes the StreamWriter, that will in turn throw away the stream. So when you try to read from the stream, you get an ObjectDisposedException.
StreamWriter is a horrible violation of the "clean up your own mess" rule. It tries to clean up someone else's mess, whether they wanted it to or not.
(Imagine if you tried this in real life. Try explaining to the cops why you broke into someone else's house and started throwing all their stuff into the trash...)
For that reason, I consider StreamWriter (and StreamReader, which does the same thing) to be among the very few classes where "if it implements IDisposable, you should call Dispose" is wrong. Never call Dispose on a StreamWriter that was created on an existing stream. Call Flush() instead.
Then just make sure you clean up the Stream when you should. (As Joe pointed out, ASP.NET disposes the Response.OutputStream for you, so you don't need to worry about it here.)
Warning: if you don't Dispose the StreamWriter, then you do need to call Flush() when you're done writing. Otherwise you could have data still being buffered in memory that never makes it to the output stream.
My rule for StreamReader is, pretend it doesn't implement IDisposable. Just let it go when you're done.
My rule for StreamWriter is, call Flush where you otherwise would have called Dispose. (This means you have to use a try..finally instead of a using.)
If an exception occurs without the using block and kills the program, you will be left with openconnections. The using block will always close the connection for you, similiar to if you were to use try{}catch{}finally{}
Eventually, the writer will be cleaned up. When this happens is up to the garbage collector, who will notice that the Dispose for the command has not been called, and invoke it. Of course, the GC may not run for minutes, hours or days depending on the situation. If the writer is holding an exclusive lock on say, a file, no other process will be able to open it, even though you're long finished.
The using block ensures the Dispose call is always made, and hence that the Close is always called, regardless of what control flow occurs.
Wrapping the StreamWriter in a using block is pretty much equivalent of the following code:
StreamWriter writer;
try
{
writer = new StreamWriter(Response.OutputStream);
writer.WriteLine("col1,col2,col3");
writer.WriteLine("1,2,3");
}
catch
{
throw;
}
finally
{
if (writer != null)
{
writer.Close();
}
}
While you could very well write this code yourself, it is so much easier to just put it in a using block.
In my opinion it's necessary to wrap any class that implements IDisposable in a using block. The fact that a class implements IDisposable means that the class has resources that need to be cleaned up.
My rule of thumb is, if I see Dispose listed in intellisense, I wrap it in a using block.
the using block calls dispose() when it ends. It's just a handy way of ensuring that resources are cleaned up in a timely manner.
In almost every case, if a class implements IDisposable, and if you're creating an instance of that class, then you need the using block.
While it's good practice to always dipose disposable classes such as StreamWriter, as others point out, in this case it doesn't matter.
Response.OutputStream will be disposed by the ASP.NET infrastructure when it's finished processing your request.
StreamWriter assumes it "owns" a Stream passed to the constructor, and will therefore Close the stream when it's disposed. But in the sample you provide, the stream was instantiated outside your code, so there will be another owner who is responsible for the clean-up.

Categories

Resources