Some advanced questions on the using statement - c#

I know there are a number of threads on here about how to use the using statement and calling the Dispose() method. I have read the majority of these threads.
If I call Dispose(), does it call Close()?
If I want to use an object (say SqlDataReader), but then use it again in another code block, should I not call Dispose()? Which also means to omit the using statement.
Also, to clarify, if a FileStream is wrapping a StreamWriter and I call dispose on the FileStream, this will call Flush(), Close() and Dispose() (depending on whether Dispose() calls Close()) on the StreamWriter, right? Likewise, if I call Close on the FileStream, this will only call Flush() and Close() on the FileStream.
Is checking IL a good way to answer these questions about what is happening under the hood?

"If I call Dispose(), does it call Close()?"
In theory, it should. The BCL classes all do this, but it is up to the library author to correctly handle this. If the library you are using is done correctly, Dispose() should also Close() [and Close() will Dispose() - the calls should be interchangable].
"If I want to use an object (say SqlDataReader), but then use it again in another code block, should I not call Dispose()? Which also means to omit the using statement."
Correct. If you use the using statement, it will always call Dispose(). This will close the data reader before your other block can use it.
"Also, to clarify, if a FileStream is wrapping a StreamWriter and I call dispose on the FileStream, this will call Flush(), Close() and Dispose() (depending on whether Dispose() calls Close()) on the StreamWriter, right? Likewise, if I call Close on the FileStream, this will only call Flush() and Close() on the FileStream."
If you are wrapping a FileStream around a StreamWriter, I highly recommend treating them consistently. Use a single using statement with both members, so they are both disposed of at the end of the block. This is the safest, most clean approach.
"Is checking IL a good way to answer these questions about what is happening under the hood?"
It is a way - although a more difficult way. Read up on MSDN about using and streams, and the documentation will explain it in simpler terms than trying to parse the IL. The IL will tell you EXACTLY what happens, though, if you are curious.

If I call Dispose(), does it call Close()?
Close() and Dispose() do the same if implemented properly; it is just a naming thing. It sounds more plain to close a file than to dispose it. See Implementing Finalize and Dispose to Clean Up Unmanaged Resources esspecialy 'Customizing a Dispose Method Name'.
If I want to use an object (say SqlDataReader), but then use it again in another code#
block, should I not call Dispose()? Which also means to omit the using statement.
Yes, because the object gets disposed on exiting the using block.
Also, to clarify, if a FileStream is wrapping a StreamWriter and I call dispose on the > FileStream, this will call Flush(), Close() and Dispose() (depending on whether Dispos()
calls Close()) on the StreamWriter, right? Likewise, if I call Close on the FileStream, > this will only call Flush() and Close() on the FileStream.
It is the other way; a StreamWriter is based on an underlying stream an closing the StreamWriter closes the underlying stream that may be a FileStream; see the MSDN for reference. Hence a single using statement for the StreamWriter is sufficent.

If I call Dispose(), does it call Close()?
Calling Dispose should take any required actions to dispose of the resource, which should be similar, if not identical to, calling Close. This, however, is an implementation detail and not necessarily guaranteed (though we can expect that the BCL follows this guideline).
If I want to use an object (say SqlDataReader), but then use it again in another code block, should I not call Dispose()? Which also means to omit the using statement.
If you want to use the object again, you definitely should not dispose it. However, you should typically use two separate connections if you're going to the database two separate times. It's generally not a good idea to keep an IDataReader around an longer than is needed to grab your needed data.
Also, to clarify, if a FileStream is wrapping a StreamWriter and I call dispose on the FileStream, this will call Flush(), Close() and Dispose() (depending on whether Dispose() calls Close()) on the StreamWriter, right? Likewise, if I call Close on the FileStream, this will only call Flush() and Close() on the FileStream.
Disposing an object that wraps another disposable object should call Dispose on the interior object. Calling Close on a FileStream will call its Dispose method under the good, so it will also act on both streams.
Is checking IL a good way to answer these questions about what is happening under the hood?
Checking IL will definitely answer most of these questions definitively. As #Rich says, you can also just try debugging your own Dispose implementations. There is also, of course, MSDN documentation to start with before you try to figure it out yourself, and Reflector if you don't want to muck around in IL.

If I call Dispose(), does it call Close()?
Not necessarily. I sometimes use Reflector to check what actually happens in Close and Dispose.
If I want to use (...) it again in another code block, should I not call Dispose()?
Correct. Call Dispose when you're done. But that doesn't mean you always want to keep your object alive for a long time - you can sometimes benefit from creating multiple instances (multiple using constructs) -- e.g. You might wan to close a connection as soon as possible, but then create a new one again when you need it.
As you said, there are lot of resources on that, but I will include the MSDN link for some guidelines: Implementing Finalize and Dispose to Clean Up Unmanaged Resources.

An easier way to debug this than going through the IL code would be to derive from your IDisposable, override the necessary methods doing nothing but calling base.[Method Name](), and set a breakpoint in each one. Then if you wrap your derived class in a using block, you'll see the lifecycle of these calls.

No, IDisposable does not require Close(), but the object implementing IDispose may be nice enough to include it in the Dispose() method.
You should dispose it as soon as you have the piece of data you are getting from the DB. Don't leave a reader open any longer than you need. If you are doing any real work with the data, use a dataAdapter/dataset instead of reader.
No Idea. Check the Generated IL

I try to move the using clause higher up, since I prefer to use that syntax. Then call the other blocks using that resource from inside that using block.

Related

Is calling Close on a class in a using clause beneficial, harmful, or moot?

In refactoring some code, I added a "using" statement like so:
using (SerialPort serialPort = new SerialPort())
{
serialPort.BaudRate = 19200;
serialPort.Handshake = Handshake.XOnXOff;
serialPort.Open();
serialPort.Write(cmd);
serialPort.Close();
}
...but now wonder whether I can or should do away with the call to Close. I reckon so, but is it just a nicety (style points) or a veritable necessity?
It really depends on the particular class implementing IDisposable. It's perfectly possible for a badly written class that implements IDisposable NOT to properly release resources and close connections. In the specific case of the SerialPort class, the documentation states that Close() calls Dispose(). I think you should in this case be fine to put it in a using block and not call Close() manually.
It really depends on the class and if the author implemented it as recommended - implemented IDisposable correctly, and have Close do nothing but call Dispose(). In such a case, the Close() call is redundant and can be removed when wrapping the class in a using block.
This is generally speaking - in this specific case with SerialPort, they did so, so the Close() call is redundant and can be removed.
As per Richter:
Types that offer the capability to be deterministically disposed of or
closed implement the dispose pattern. The dispose pattern defines
conventions a developer should adhere to when defining a type that
wants to offer explicit cleanup to a user of the type.
Being that SerialPort defines an open and close it implies that it can be opened and closed multiple times during it's lifetime, which is mutually exclusive from it being disposed (e.g. never used again)
But back to your original question, yes - in this case it is redundant, decompiling the SerialPort object reveals that dispose closes the port for you when called:
protected override void Dispose(bool disposing)
{
if (disposing && this.IsOpen)
{
this.internalSerialStream.Flush();
this.internalSerialStream.Close();
this.internalSerialStream = (SerialStream) null;
}
base.Dispose(disposing);
}
If an exceptional condition arises in Dispose, it is usually better to have Dispose throw the exception than complete silently (whether it's better to stifle the exception in any particular situation will depend upon whether an exception is already pending and there is as yet alas no mechanism via which Dispose can know when that's the case). Because there is no good way to handle an exception within Dispose, it's often a good idea to ensure when possible that any actions which could go wrong if done within a Dispose will be done before the Dispose is invoked.
If Dispose were the only method of cleanup in the normal case, then having it stifle exceptions would pose a significant risk that problems could occur but go undetected. Having a class support both Close and using, and having clients call Close in the main-line case, will allow such risk to be reduced (if an exception is pending, Dispose will get called without Close, and thus any exceptions on cleanup will get stifled but code will know that something went wrong somewhere because of the pending exception; if no exception occurs before Close, the fact that it's not being called in a Dispose cleanup context will mean that it can assume no exception is pending, and it may thus safely throw one of its own).
There's not much consistency in the exception-handling practices of Dispose and Close, but I would recommend calling Close on principle. Depending upon how Dispose and Close are implemented, explicitly calling Close before the implicit Dispose may or may not be helpful, but it should be at worst harmless. Given the possibility of its being helpful (if not in the present version of a class, perhaps in a future version) I would suggest it as a general habit.

Should I dispose readonly FileStream

I have a readonly FileStream which is a method local variable:
public void SomeMethod()
{
var fileStream = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
... //some stream operations
}
Should I call Dispose (explicitly or by "using") at the end of the method? What will it change?
It doesn't matter what it does, IDisposable is implemented by FileStream, and so you need to call Dispose implicitly or explicitly when you've finished using it. It is part of the contract of using the class in your code.
I think it's best to wrap that in a using statement. You also need exception handling if you really want that code to be robust. It will work as it is now, it's just bad practice.
It is a must to dispose any instance implementing IDisposable and a good practice to dispose it trough using statement.
Don't think that analyzing every case in particular would help.
If you fail to dispose, the FileStream won't be closed until the GC kicks in (non-deterministically).
And until this happens, you will be holding an open file handle, preventing some types of access to the file (e.g. writing, deletion).
Note that specifying FileShare.ReadWrite won't necessarily help - if another writer attempts to open the file with FileShare.None (e.g. by calling File.OpenWrite), he won't be able to do so until you close the file.
So, yes, do close the file, with a using statement.
If an object can be disposed, you should dispose it as early as you don't need it anymore. From FileStream Class topic:
If a process terminates with part of a file locked or closes a file
that has outstanding locks, the behavior is undefined.
As everyone suggested: dispose every IDisposable, preferably with using.
Now for files there could be special case when you really want to block everyone else from accessing/modifying the file. In this case you'd still dispose file at some point, but this "some point" can be significantly later in the code/application lifetime.

For Microsoft built classes that inherit IDisposable, do I explicitly have to call Dispose?

Regarding the Microsoft built classes that inherit IDisposable, do I explicitly have to call Dispose to prevent memory leaks?
I understand that it is best practice to call Dispose (or better yet use a using block), however when programming, typically I don't always immediately realise that a class inherits from IDisposable.
I also understand that Microsoft implementation of IDisposable is a bit borked, which is why they created the article explaining the correct usage of IDisposable.
Long story short, in which instances is it okay to forget to call Dispose?
There are a couple of issues in the primary question
Do I explicitly have to call Dispose to prevent memory leaks?
Calling Dispose on any type which implements IDisposable is highly recomended and may even be a fundamental part of the types contract. There is almost no good reason to not call Dispose when you are done with the object. An IDisposable object is meant to be disposed.
But will failing to call Dispose create a memory leak? Possibly. It's very dependent on what exactly that object does in it's Dispose method. Many free memory, some unhook from events, others free handles, etc ... It may not leak memory but it will almost certainly have a negative effect on your program
In which instances is it okay to forget to call Dispose?
I'd start with none. The vast majority of objects out there implement IDisposable for good reason. Failing to call Dispose will hurt your program.
It depends on two things:
What happens in the Dispose method
Does the finalizer call Dispose
Dispose functionlity
Dispose can do several type of actions, like closing a handle to a resource (like file stream), change the class state and release other components the class itself uses.
In case of resource being released (like file) there's a functionality difference between calling it explicitly and waiting for it to be called during garbage collection (assuming the finalizer calls dispose).
In case there's no state change and only components are released there'll be no memory leak since the object will be freed by the GC later.
Finalizer
In most cases, disposable types call the Dispose method from the finalizer. If this is the case, and assuming the context in which the dispose is called doesn't matter, then there's a high chance that you'll notice no difference if the object will not be disposed explicitly. But, if the Dispose is not called from the finalizer then your code will behave differently.
Bottom line - in most cases, it's better to dispose the object explicitly when you're done with it.
A simple example to where it's better to call Dispose explicitly: Assuming you're using a FileStream to write some content and enable no sharing, then the file is locked by the process until the GC will get the object. The file may also not flush all the content to the file so if the process crashes in some point after the write was over it's not guaranteed that it will actually be saved.
It can be safe to not call Dispose, but the problem is knowing when this is the case.
A good 95% of IEnumerator<T> implementations have a Dispose that's safe to ignore, but the 5% is not just 5% that'll cause a bug, but 5% that'll cause a nasty hard to trace bug. More to the point, code that gets passed an IEnumerator<T> will see both the 95% and the 5% and won't be able to dynamically tell them apart (it's possible to implement the non-generic IEnumerable without implementing IDisposable, and how well that turned out can be guessed at by MS deciding to make IEnumerator<T> inherit from IDisposable!).
Of the rest, maybe there's 3 or 4% of the time it's safe. For now. You don't know which 3% without looking at the code, and even then the contract says you have to call it, so the developer can depend on you doing so if they release a new version where it is important.
In summary, always call Dispose(). (I can think of an exception, but it's frankly too weird to even go into the details of, and it's still safe to call it in that case, just not vital).
On the question of implementing IDisposable yourself, avoid the pattern in that accursed document.
I consider that pattern an anti-pattern. It is a good pattern for implementing both IDisposable.Dispose and a finaliser in a class that holds both managed and unmanaged resources. However holding both managed IDisposable and unmanaged resources is a bad idea in the first place.
Instead:
If you have an unmanaged resource, then don't have any unmanaged resources that implement IDisposable. Now the Dispose(true) and Dispose(false) code paths are the same, so really they can become:
public class HasUnmanaged : IDisposable
{
IntPtr unmanagedGoo;
private void CleanUp()
{
if(unmanagedGoo != IntPtr.Zero)
{
SomeReleasingMethod(unmanagedGoo);
unmanagedGoo = IntPtr.Zero;
}
}
public void Dispose()
{
CleanUp();
GC.SuppressFinalize(this);
}
~HasUnmanaged()
{
CleanUp();
}
}
If you have managed resources that need to be disposed, then just do that:
public class HasUnmanaged : IDisposable
{
IDisposable managedGoo;
public void Dispose()
{
if(managedGoo != null)
managedGoo.Dispose();
}
}
There, no cryptic "disposing" bool (how can something be called Dispose and take false for something called disposing?) No worrying about finalisers for the 99.99% of the time you won't need them (the second pattern is way more common than the first). All good.
Really need something that has both a managed and an unmanaged resource? No, you don't really, wrap the unmanaged resource in a class of your own that works as a handle to it, and then that handle fits the first pattern above and the main class fits the second.
Only implement the CA10634 pattern when you're forced to because you inherited from a class that did so. Thankfully, most people aren't creating new ones like that any more.
It is never OK to forget to call Dispose (or, as you say, better yet use using).
I guess if the goal of your program is to cause unmanaged resource leaks. Then maybe it would be OK.
The implementation of IDisposable indicates that a class uses un-managed resources. You should always call Dispose() (or use a using block when possible) when you're sure you're done with the class. Otherwise you are unnecessarily keeping un-managed resources allocated.
In other words, never forget to call Dispose().
Yes, always call dispose. Either explicitly or implicitly (via using). Take, for example, the Timer class. If you do not explicitly stop a timer, and do not dispose it, then it will keep firing until the garbage collector gets around to collecting it. This could actually cause crashes or unexpected behavior.
It's always best to make sure Dispose is called as soon as you are done with it.
Microsoft (probably not officially) says it is ok to not call Dispose in some cases.
Stephen Toub from Microsoft writes (about calling Dispose on Task):
In short, as is typically the case in .NET, dispose aggressively if
it's easy and correct to do based on the structure of your code. If
you start having to do strange gyrations in order to Dispose (or in
the case of Tasks, use additional synchronization to ensure it's safe
to dispose, since Dispose may only be used once a task has completed),
it's likely better to rely on finalization to take care of things. In
the end, it's best to measure, measure, measure to see if you actually
have a problem before you go out of your way to make the code less
sightly in order to implement clean-up functionality.
[bold emphasize is mine]
Another case is base streams
var inner = new FileStrem(...);
var outer = new StreamReader(inner, Encoding.GetEncoding(1252));
...
outer.Dispose();
inner.Dispose(); -- this will trigger a FxCop performance warning about calling Dispose twice.
(I have turned off this rule)

Why must I Close() a file in C#?

I know this might seem silly, but why does the following code only work if I Close() the file? If I don't close the file, the entire stream is not written.
Steps:
Run this code on form load.
Close form using mouse once it is displayed.
Program terminates.
Shouldn't the file object be flushed or closed automatically when it goes out of scope? I'm new to C#, but I'm used to adding calls to Close() in C++ destructors.
// Notes: complete output is about 87KB. Without Close(), it's missing about 2KB at the end.
// Convert to png and then convert that into a base64 encoded string.
string b64img = ImageToBase64(img, ImageFormat.Png);
// Save the base64 image to a text file for more testing and external validation.
StreamWriter outfile = new StreamWriter("../../file.txt");
outfile.Write(b64img);
// If we don't close the file, windows will not write it all to disk. No idea why
// that would be.
outfile.Close();
C# doesn't have automatic deterministic cleanup. You have to be sure to call the cleanup function if you want to control when it runs. The using block is the most common way of doing this.
If you don't put in the cleanup call yourself, then cleanup will happen when the garbage collector decides the memory is needed for something else, which could be a very long time later.
using (StreamWriter outfile = new StreamWriter("../../file.txt")) {
outfile.Write(b64img);
} // everything is ok, the using block calls Dispose which closes the file
EDIT: As Harvey points out, while the cleanup will be attempted when the object gets collected, this isn't any guarantee of success. To avoid issues with circular references, the runtime makes no attempt to finalize objects in the "right" order, so the FileStream can actually already be dead by the time the StreamWriter finalizer runs and tries to flush buffered output.
If you deal in objects that need cleanup, do it explicitly, either with using (for locally-scoped usage) or by calling IDisposable.Dispose (for long-lived objects such as referents of class members).
Because Write() is buffered and the buffer is explicitly flushed by Close().
Streams are objects that "manage" or "handle" non-garbage collected resources. They (Streams) therefore implement the IDisposable interface that, when used with 'using' will make sure the non-garbage collected resources are clean up. try this:
using ( StreamWriter outfile = new StreamWriter("../../file.txt") )
{
outfile.Write(b64img);
}
Without the #Close, you can not be sure when the underlying file handle will be properly closed. Sometimes, this can be at app shutdown.
Because you are using a streamwriter and it doesn't flush the buffer until you Close() the writer. You can specify that you want the writer to flush everytime you call write by setting the AutoFlush property of the streamwriter to true.
Check out the docs. http://msdn.microsoft.com/en-us/library/system.io.streamwriter.aspx
If you want to write to a file without "closing", I would use:
System.IO.File
Operating system cache write to block devices to enable the OS to have better performance. You force a write by flushing the buffer after a write of setting the streamwriter to autoflush.
Because the C# designers were cloning Java and not C++ despite the name.
In my opinion they really missed the boat. C++ style destruction on scope exit would have been so much better.
It wouldn't even have to release the memory to be better, just automatically run the finalizer or the IDisposable method.

Method returns an IDisposable - Should I dispose of the result, even if it's not assigned to anything?

This seems like a fairly straightforward question, but I couldn't find this particular use-case after some searching around.
Suppose I have a simple method that, say, determines if a file is opened by some process. I can do this (not 100% correctly, but fairly well) with this:
public bool IsOpen(string fileName)
{
try
{
File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.None);
}
catch
{
// if an exception is thrown, the file must be opened by some other process
return true;
}
}
(obviously this isn't the best or even correct way to determine this - File.Open throws a number of different exceptions, all with different meanings, but it works for this example)
Now the File.Open call returns a FileStream, and FileStream implements IDisposable. Normally we'd want to wrap the usage of any FileStream instantiations in a using block to make sure they're disposed of properly. But what happens in the case where we don't actually assign the return value to anything? Is it still necessary to dispose of the FileStream, like so:
try
{
using (File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.None));
{ /* nop */ }
}
catch
{
return true;
}
Should I create a FileStream instance and dispose of that?
try
{
using (FileStream fs = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.None));
}
...
Or are these totally unnecessary? Can we simply call File.Open and not assign it to anything (first code example), and let the GC dispose of it right away?
Yes, you should definitely dispose of the FileStream. Otherwise the stream will remain open and the file won't be usable until a finalizer happens to clean it up.
The important thing here is ownership: for File.Open, the caller is assumed to "own" the stream returned to it - and if you own something which implements IDisposable, it's your responsibility to dispose of it.
Compare this with the situation of Image.FromStream: in that case, you pass in a stream and the Image then assumes that it owns that stream. You mustn't close the stream yourself, in that case - you have to dispose of the image when you're done, and it will dispose of the stream.
Calling a static method which returns something disposable almost always assumes that the caller takes ownership of the resource. Ditto constructors (which are effectively static methods.)
The irony in this case is that if you don't dispose of the stream returned by File.Open, you'll have found that the file is usable - at the same time as making it unusable until some indeterminate time.
If a method returns an IDisposable, I personally would always put it in a using block. Even if I don't assign the return value to anything.
Even if you don't assign it to a variable, the disposable object is still created. Dispose is not going to be called automatically. The only difference will be that the returned object will become immediately eligible for garbage collection, because there are no (strong) references to it.
The garbage collector does not call Dispose automatically when it reclaims an object. However, most IDisposable types provide a finalizer (which will be called just before the GC reclaims an object) that invokes Dispose as a fallback strategy (safety net) — study the IDisposable pattern to see how this is done:
~SomeClass // <-- the finalizer method will usually call Dispose;
{ // but you have no control over when it will be called!
Dispose(false);
}
Remember that you don't know when the garbage collector will run (because it's non-deterministic). Therefore, you also don't know when the finalizer method will be called. And because of that -- if you haven't called Dispose explicitly (either yourself, or with a using block) -- you don't know when it will be called by the finalizer.
That's the advantage of calling Dispose explicitly: You can free resources -- or at least allow the GC to free managed resources -- as soon as you're done with them, instead of holding on to resources until the finalizer gets called sometime in the future.
Yes, you don't want to leave the FileStream opened. For one, you won't even be able to open the file yourself after that. Calling Close() is good enough, but using using is probably the preferred pattern.
There's a much bigger problem with your code however. It cannot possibly work reliably on Windows. A typical scenario:
The File.Open() call succeeds. You close it
Your thread gets pre-empted by the Windows scheduler
Another thread in another process gets a chance to run, it opens the file
Your thread regains the CPU and continues after the File.Open() call
You open the file, trusting that it will work since IsOpen() returned false.
Kaboom.
Never write code like this, failure is extremely hard to diagnose. Only ever open a file when you are ready to start reading or writing to it. And don't close it until you are done.
Extra bonus: it is now obvious that you want to use a using statement.
When you call any method that returns something, an instance of that something is being created. Just because you're not actually capturing it, doesn't make it any less "there". Therefore, in the case of an IDisposable object, the object is being created by the method you're calling in spite of the fact that you're doing nothing with it. So yes, you still need to dispose of it somehow. The first approach with the using statement seems like it should work.

Categories

Resources