Based on the information you provided, there is absolutely no reason to implement IDisposable
or a finalizer on Test
.
Only implement a finalizer to release unmanaged resources (window handle, GDI handle, file handle). You usually do not have to ever do this unless you are PInvoking the Win32 API or something. Microsoft has kindly wrapped this for you in the FileStream
so you do not have to worry about file handles.
A finalizer is meant to clean up unmanaged resources when an object is garbage collected.
Since the garbage collector might take a very long time before it decides to collect your object, you might want to have a way to trigger cleanup. No, GC.Collect()
is not the right way to do that. ;)
To allow early cleanup of native resources without having to wait for garbage collector, you implement IDisposable
on your class. This lets the caller trigger cleanup without waiting on the GC. This does not cause your object to be freed by the GC. All it does is free the native resource.
In the case where an object owns another object that is Disposable, then the owning object should also implement IDisposable
and simply call the other object's Dispose()
.
Example:
class Apple : IDisposable
{
HWND Core;
~Apple() { Free(); }
Free()
{
if(Core != null)
{
CloseHandle(Core);
Core = null;
}
}
Dispose() { Free(); }
}
class Tree : IDisposable
{
List<Apple> Apples;
Dispose()
{
foreach(var apple in Apples)
apple.Dispose();
}
}
Notice that Tree
does not have a finalizer. It implements Dispose
because it must care about Apple
cleanup. Apple
has a finalizer to make sure it cleans up the Core
resource. Apple
allows early cleanup by calling Dispose()
The reason that you do not need Dispose
and certainly do not need a finalizer is because your class Test
does not own any member field that is unmanaged or IDisposable
. You do happen to create a FileStream
, which is disposable, but you clean it up before leaving the method. It is not owned by the Test
object.
There is one exception to this case. If you are writing a class that you know will be inherited by others, and the others may have to implement IDisposable
, then you should go ahead and implement IDisposable
. Otherwise, callers won't know to dispose the object (or even be able to without casting). However, this is a code smell. Usually, you would not inherit from a class and add IDisposable
to it. If you do, it's probably poor design.