A type must implement Finalize() when it uses unmanaged resources such as file handles or database connections that must be released when the managed object that uses them is reclaimed.
But executing Finalize() has its performance bottlenecks. Read the below articles for more info.
Hence it is better if a Dispose() method is implemented and developers are encouraged to call Dispose() or Close(). We can always have Finalize() as a back-up in case the developer forgets to call Dispose(). For this we need to use the SuppressFinalize() method to prevent double execution of clean-up code.
GC class has a SuppressFinalize() method that can be called from the IDisposable.Dispose method to prevent the garbage collector from calling Object.Finalize on an object that does not require it.