Dispose doesn't get called automatically; you need to call it, or use a using block, eg.
using(Stream s = File.OpenRead(@"c:\temp\somefile.txt"))
// Do something with s
The finalizer only gets called by the GC if it exists. Having a finalizer causes your class to be collected in 2 steps; first the object is put in the finalizer queue, then the finalizer is called and the object is collected. Objects without finalizers are directly collected.
The guideline is that Dispose gets rid of managed and unmanaged resources, and the finalizer only cleans up unmanaged resources. When the Dispose method has freed the unmanaged resources it can call GC.SuppressFinalize to avoid the object from living long to be put on the finalizer queue. See MSDN for a correct sample of the dispose pattern.