I'm Using Visual Studio 2017 to write C# apps. I strive to dispose of all objects I instantiate by utilizing the "using" statement. Visual Studio warns me if I instantiate an object NOT based on a type that is implicitly convertible to 'System.IDisposable'. This example results in VS displaying the warning (C#):
using (uri = new System.Uri(stringVarWithPath))
{
}
Are all types that don't implement a Dispose method unmanaged? I ask because "Implementing a Dispose Method" (https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose) seems to imply its applicable only to unmanaged resources.
It's the other way around.
First, all types you work with in .NET are managed. But some managed types encapsulate unmanaged resources, such as Windows handles.
The types that encapsulate unmanaged resources, usually implement IDisposable
. The IDisposable
interface lets you explicitly release unmanaged resources held by these objects, by either calling Dispose()
, or putting them in using
. In the latter case, Dispose()
is called automatically when exiting the scope of the using
.
In any way, even if Dispose()
is not called on an object that implements it, well designed classes should release their unmanaged resources in Finalize()
(which is basically destructor). But Finalize()
is invoked by the GC, and we don't know how often the GC is invoked, which meakes the process of releasing resources non-deterministic. Without IDisposable
, we'd hold expensive unmanaged resources for extended periods of time, much more than might be necessary.
When a type doesn't implement IDisposable
, it is an indication that it holds no unmanaged resources, and it has no reason to be explicitly disposed (provided the type is well-designed, of course).
Note that some types that implement IDisposable
don't actually hold any unmanaged resources. For example, a class that measures time of execution can implement IDisposable
, so that it saves a timestamp in constructor, then in Dispose
it takes current timestamp and calculates elapsed time and reports it to some logging mechanism. When you put such a class inside using
, you get a convenient way of measuring execution time of your code blocks.