If I understand correctly the .net runtime will always clean up after me. So if I create new objects and I stop referencing them in my code, the runtime will clean up those
Some objects might need to clean up low-level items. Such as hardware that needs to be closed, etc.
The simplistic explanation:
Some guidelines for implementing the Finalize method:
Some guidelines for implementing the Dispose method:
There are a few (very few) cases where it may be necessary to perform a specific action when a pure managed object is no longer used, I can't come up with an example off the top of my head but I have seen a couple of legitimate uses over the years. But the main reason is to clean up any unmanaged resources that the object might be using.
So, in general, you won't need to use the Dispose/Finalize pattern unless you are using unmanaged resources.
The previous answers are good but let me emphasize the important point here once again. In particular, you said that
If I understand correctly the .net runtime will always clean up after me.
This is only partly correct. In fact, .NET only offers automatic management for one particular resource: main memory. All other resources need manual cleanup.1)
Oddly, main memory gets special status in almost all discussions about program resources. There's of course a good reason for this – main memory is often the scarcest resource. But it's worth remembering that there are other types of resources as well, that also need managing.
1) The usual attempted solution is to couple the lifetime of other resources to the lifetime of memory locations or identifiers in the code – hence the existence of finalizers.
Mainly for non-managed code, and interaction with non-managed code. "Pure" managed code should never need a finalizer. Disposable on the other hand is just a handy pattern to force something to be released when you are done with it.