For your #1: as you correctly wrote on your question, the main reason to use Dispose is to free resources from unmanaged resources (like file handles, database connections, etc), but there is one more case where we can call dispose to do some things related with managed resources and that is disconnecting event handlers. There is a really good explanation about this here.
Answering your #2, finalizers are not recommended because they introduce performance issues and because of that, you should avoid using them if you can use better solutions. As stated in this fragment from "Effective C#" by Bill Wagner:
A finalizer is a defensive mechanism that ensures your objects always
have a way to release unmanaged resources
And if you keep reading...
Finalizers are the only way to guarantee that unmanaged resources
allocated by an object of a given type are eventually released. But
finalizers execute at nondeterministic times, so your design and
coding practices should minimize the need for creating finalizers, and
also minimize the need for executing the finalizers that do exist.
So the finalizer seem to be in the only thing you can do to make sure the unmanaged resources are released, so maybe it was the reason you were looking for (I don't really know the Microsoft reason to do it, sorry).
To answer your #3 I would need an exact code example to what you really mean, but I wil try to guess. I suppose you are talking about the next two different scenarios:
Calling myObject.Dispose() after using it, explicit way. For example, we can create an instance, use it and then call Dispose:
myObject = new MyObject()
// More code here...
myObject.Dispose();
That will be ok if you are sure that between the creation of your instance and the calling to the Dispose method there is no exception in your code, which could cause the call to Dispose to be missed. Of course you can always use a finally block:
try {
MyObject myObject = new MyObject()
(...)
}
catch (Exception) {
// manage exception
}
finally {
if (myObject != null)
myObject.Dispose();
}
Calling Dispose using the IDisposable interface through using. It is basically the same that the previous with the finally block, but it will be created "automatically":
using (MyObject myObject = new MyObject()) {
// your code here
}
You can check the docs here.
And answering your #4. I think that this is a good answer, but do not forget to read the comments. So, in short, if it has a Dispose method, it should be called.