I am writing an ASP.NET Web API. As part of this, I have a class that I found out, during testing, needs to implement IDisposable
to ensure managed resources are freed.
So, I implemented IDisposable
in my class, and put the code necessary to free the resources in the Dispose()
method.
There are many places in my code (hundreds) where I instantiate this object, and in the same line call a method on the new instance. I only need the instance to call the single method.
Here's an example:
// MyObject, a class that needs to be disposed of.
public class MyObject : IDisposable
{
private AnObjectThatMustBeDisposed localObject;
public MyObject()
{
localObject = SomeLibrary.SomeProject.AnObjectThatMustBeDisposed.Create();
}
public void doOperationOne()
{
localObject.DoSomething(1);
}
public string getOperationTwo()
{
return localObject.DoSomething(2);
}
public string getOperationThree()
{
return localObject.DoSomething(3);
}
public bool getOperationFour(string input)
{
return localObject.DoSomethingSpecial(4,input.ToLower());
}
...
public void getOperationOneHundred(DateTime input)
{
localObject.DoSomethingElse(100,input);
}
public void Dispose()
{
localObject.CloseResources();
localObject.FreeUpMemory();
localObject.Close();
localObject.Dispose();
}
}
// A class that makes use of MyObject
public class MyLibraryThatUsesMyObject
{
public void Method1()
{
new MyObject().doOperationOne();
}
public string Method2()
{
return new MyObject().getOperationTwo();
}
public int Method3()
{
return new MyObject().getOperationThree();
}
public bool Method4(string testString)
{
if (testString.Length > 6)
{
if (new MyObject().getOperationFour(testString)) return true;
else return false;
}
else return false;
}
...
public void Method100()
{
new MyObject().doOperationOneHundred(DateTime.Now);
}
}
My question is: Does .NET automatically Dispose()
objects when they fall out of scope? Or, do I actually have to do this...
public void Method1()
{
using (MyObject o = new MyObject())
{
o.DoOperationOne();
}
}
...to each method? It wouldn't be hard if I had two or three methods, but if I have tons of methods, this refactoring could take quite a while.
I am not sure how ASP.NET handles requests as they complete - i.e. does the framework give code time to Dispose()
things, or does it "cut off" execution as soon as the return
is called, not letting things dispose?
The fact that, without implementing IDisposable
myself, things inside the MyObject
class are failing due to unreleased resources causing leaks, it feels like .NET does not automatically Dispose
things. So, if that's the case, can I do something so I don't have to refactor hundreds of methods?
EDIT: I tried simply implementing IDisposable
, but my unit test was still able to produce a resource leak. So it would appear that my suspicion that .NET is not automatically disposing is correct. So now my question becomes - how can I force disposing without having to refactor hundreds of methods?
Dispose is not automatically called. If you don't call .Dispose()
(either explicitly or via a using
statement) the method will never be called.
The only caveat is methods that are implemented with the pattern
public void Dispose()
{
GC.SuppressFinalize(this);
Dispose(true);
}
~MyClass()
{
Dispose(false);
}
bool _isDisposed = false;
protected virtual void Dispose(bool disposeing)
{
if(_isDisposed)
return;
_isDisposed = true;
if(disposing)
{
//Disposed managed code here
}
//Dispose unmanaged code only here.
}
Will have Dispose(false)
called on it when the object is finalized, but you are not allowed to dispose (or even access) managed objects (i.e: other stuff that implements .Dispose()
) when disposing
is false
.
You will need to refactor your code if you want your resources disposed correctly.
There is a really, really, good article written by Stephen Cleary "IDisposable: What Your Mother Never Told You About Resource Deallocation" that does a very good job explaining how Dispose works and how to correctly write your own disposeable objects (for example, that caveat pattern I mentioned above is recommended by Microsoft but is actually a very bad pattern to do. Classes should only either hold only managed resources or derive from SafeHandle
and only hold a unmanaged resource and possibly other SafeHandles
. You should never have a class that holds both managed and unmanaged resources nor a single class that holds multiple unmanaged resources)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With