0

It has come to my attention that certain resources should be disposed of after utilizing them or closed etc; Is there a rule of thumb as to what exactly should be closed / disposed? Example - when you use StreamWriter , you want to close that when you are done to avoid errors etc. What are things that should absolutely be closed / disposed of and when?

ModS
  • 806
  • 2
  • 15
  • 28
  • 3
    If it implements IDisposable wrap in a using statement. – Mitch Wheat Oct 15 '14 at 01:32
  • 1
    @MitchWheat: Unfortunately `using` is usable in only a fraction of scenarios. For example, it helps you not at all with member fields of disposable types. (C++/CLI "stack semantic" feature is much better in this regard) – Ben Voigt Oct 15 '14 at 01:33
  • 1
    @ Ben Voigt: I find that it is useable most places. – Mitch Wheat Oct 15 '14 at 01:34
  • 1
    [Some good info in this thread](http://stackoverflow.com/questions/538060/proper-use-of-the-idisposable-interface). – Grant Winney Oct 15 '14 at 01:34
  • @MitchWheat: Variables of interface type are another place `using` is less than helpful. The concrete type might also implement `IDisposable`, but the compiler doesn't put in logic like `(obj as IDisposable).?Dispose()`, it just errors. – Ben Voigt Oct 15 '14 at 01:47

2 Answers2

2

The rule of thumb is... (drumroll, curtains pull back, pyrotechnics go up, and as the smoke clears)

  • Every time you are done using an object, if and only if the type1 implements System.IDisposable

Oh, you were expecting something complicated? Sorry to disappoint.


1The concrete type of the object. Sometimes that needs a runtime check, e.g. with IEnumerator implementations.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • 1
    One can perhaps add that the garbage collector will in many cases eventually do that work for you... – Willem Van Onsem Oct 15 '14 at 01:38
  • 2
    @CommuSoft: If the object doesn't benefit from deterministic destruction (which the GC never provides), it shouldn't be implementing `IDisposable`. – Ben Voigt Oct 15 '14 at 01:39
  • 1
    well `Stream` offers `IDisposable`, but it is mainly used to garbage collect "large files" as soon as possible since a garbage collector tends to wait until the program needs additional memory. In other words: if the resource is "small", no need to dispose of it in many cases... – Willem Van Onsem Oct 15 '14 at 01:41
  • 1
    @CommuSoft: `MemoryStream` is the only kind of `Stream` I can think of where prompt disposal is unimportant. – Ben Voigt Oct 15 '14 at 01:42
  • Ben, how do you check for this implementation? do you just look for the dispose method* and if it is available you know you need to do this at some point? The reason i ask is because you said if it implements idisposable – ModS Oct 15 '14 at 01:44
  • @CommuSoft: I don't understand your obsession with "large" files. Any file will be kept open if not disposed/closed correctly, preventing deletion/reopening/opening in other applications, and sometimes even send antivirus into conniptions. – Ben Voigt Oct 15 '14 at 01:44
  • 1
    @ModS: You can either read the documentation, or test `some_object is IDisposable` (or use `as` and a null check, benefit of that is you also have a reference you can immediately use to call `Dispose()`) – Ben Voigt Oct 15 '14 at 01:45
  • @BenVoigt: not necessarily. You can set up your system in such way that even though a file opened (to write content to), other programs still have access to it. And furthermore as pointed out in many OS books, deadlocks are quite scarce in the context of multiple programs (not in the context of threads), since most programs use only "local files". Of course one should be careful when designing programs with respect to deadlocks. If however you open a config file of your program, it is not that likely another program will need access. – Willem Van Onsem Oct 15 '14 at 01:47
  • 1
    @CommuSoft: I've frequently encountered cases (my own and others') where either (1) the file is filled with data to be immediately processed my another tool, or (2) the file is saved by the user, who immediately wants to go do something with it, such as email it as an attachment. Most programs typically refuse to open files which are still open for writing, to avoid data corruption (reading a partially written file). – Ben Voigt Oct 15 '14 at 01:50
  • 1
    @CommuSoft: The read-only case of course causes problems less often... but a user might want to change the configuration file, which is after all why those settings are stored in a file in the first place. – Ben Voigt Oct 15 '14 at 01:51
1

As @BenVoigt says, you should dispose of an IDisposable if you are done using that resource. C# introduced the using keyword for developers ease of use:

Example:

using (FileStream SourceStream = File.Open("file.ext", FileMode.Open)) {
  //do something with the file
}

This keyword is a syntactical way to ensure that you dispose of your resource once you exit a method, etc. Of course some resources can be shared over multiple methods, threads, etc. so this language construct is not always available.

In many cases however, it's not that bad to forget to dispose of such object. If the program does no longer refers to it, the garbage collector will eventually walk by and dispose of it itself. Disposing of objects is however useful if the resource is large (a large file) or uses network resources (e.g.: a database connection). Since it releases resources that can be reused by other programs/users/clients/...

Furthermore disposing of objects is useful if they can be shared over multiple processes, threads, etc. like for instance files.: say you write to a file, then other programs need to wait until the write process has ended. If however program A waits for a file in use by process B and vice versa, a deadlock will occur: both programs wait for each other but don't give up their own resource. By disposing of such resources as soon as possible, most deadlocks will be prevented.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • 1
    Or takes a lock on any resource. It's so easy to cause access denied error reopening a file, because a `FileStream` wasn't properly closed/disposed and is still holding it open without sharing. – Ben Voigt Oct 15 '14 at 01:40
  • 1
    @BenVoigt: modified with an example of deadlock. – Willem Van Onsem Oct 15 '14 at 01:45