Would the garbage collector automatically free the unmanaged resources (whatever, actually) associated with some IDisposable
instance if, for example, I forgot to write using
statement?
Obviously, I don't know when this would happen, but is it fine to leave the IDisposable
to the GC
when I don't care about those resources and I'm fine with that they will be disposed eventually?
Would the garbage collector automatically free the unmanaged resources (whatever, actually) associated with some IDisposable instance if, for example, I forgot to write using statement?
Usually, but not necessarily. The author of a disposable resource needs to do the right thing.
Obviously, I don't know when this would happen, but is it fine to leave the IDisposable to the GC when I don't care about those resources and I'm fine with that they will be disposed eventually?
Your question presupposes a falsehood. The garbage collector never calls Dispose, ever. Rather, the garbage collector calls the destructor (or "finalizer" if you prefer). It is the destructor which might or might not call Dispose for the forgetful user.
Your question also indicates a bad attitude. You might not care if the resources are freed late but another program certainly might care! What if your customer is running two programs that both try to access the same unmanaged resource, one written by you and one written by someone else? Be a good citizen; release your scarce resources as soon as you are done with them so that other programs can use them. That's the real purpose of "using" -- it's to be polite by ensuring that scarce resources are reclaimed quickly.
A correct implementation of the Dispose pattern will ensure that the destructor cleans up the unmanaged resources if the user forgets to call Dispose, and will ensure that the destructor does NOT clean up the resources if they remember.
If you are the person writing the implementation of Dispose for a class that owns unmanaged resources it is your responsibility to get the destructor code right for the case where the user does not call Dispose correctly. The correct way to write this code is extremely well documented; follow the pattern. See Jon's comments for some helpful links.
Note also that if you are writing such a class then you are required to also make it work in scenarios in which it is impossible for the user to call Dispose. For example, suppose the constructor allocates two unmanaged resources, and between the allocation of the first and second, an exception is thrown and caught outside of the constructor. There's then no way for the user to ever call Dispose because the assignment of the new object reference happens after the constructor runs successfully, and the constructor never finished running successfully. How is the first unmanaged resource freed? Only the destructor can free it. The destructor has to be robust in the face of such scenarios; the object destructed might never have been fully constructed so you cannot rely on any invariant of the constructor.