Reputation: 3284
I have bit of an odd question and I could't find a clear answer to this even though there are threads bordering around the same question.
Question:If I set an object to null, will that cause the dispose method (implemented) be called deterministically? For example in the following code, by setting pricingEnvironment object to null, will Dispose get called immedietly? I understand that the finalizer will kick off for pricingEnvironment object at some point if Dispose is not called though.
Code:
public interface IPricingService
{
double GetPrice(string instrument);
}
public interface IPricingEnvironment:IDisposable
{
void Initialize();
}
public class PricingEnvironment : IPricingEnvironment
{
public void Dispose()
{
DisposeObject();
}
public void Initialize()
{
//initialize something leaky
}
private void DisposeObject()
{
//release some leaky unmanaged resource
}
~PricingEnvironment()
{
DisposeObject();
}
}
public class PricingService:IPricingService, IDisposable
{
private IPricingEnvironment pricingEnvironment;
public PricingService()
{
pricingEnvironment = new PricingEnvironment();
}
public double GetPrice(string instrument)
{
pricingEnvironment.Initialize();
return 1d;
}
public void Dispose()
{
//Will this dispose the leaky resource used by pricing environment deterministically?
pricingEnvironment = null;
}
}
Thanks, -Mike
Upvotes: 4
Views: 475
Reputation: 8708
I guess you're confusing disposing with being garbage collected.
Dispose frees non-managed resources (a Database connection or a file handle)
GC frees occupied memory by no longer used objects
Disposing is deterministic because it runs when you call Dispose (whether explicitly or implicitly in a using
block)
Garbage collection is, by nature, non-deterministic. It runs when it fits to. Only then it may free a memory reference. For instance, If GC is running a generation level different from the one where the object is currently on, it will not be collected.
You may run GC explicitly by calling GC.Collect()
but ask yourself if you should be second guessing the GC.
Upvotes: 0
Reputation: 42414
No, it will not.
do this:
public void Dispose()
{
// check if object has IDisposble implemented
IDisposable disposePricing = pricingEnvironment as IDisposable;
if (disposePricing!=null)
{
disposePricing.Dispose();
}
}
and have a read on this CLR Inside Out article from 2007
Upvotes: 1
Reputation: 176159
There is no guarantee in .NET that the finalizer is ever called. The garbage collector may simply not call it (e.g. because there simply is no need for the garbage collector to ever free memory), and in the case one finalizer throws an exception, other finalizers will not execute (see MSDN). You can even suppress finalizers if you call SuppressFinalizer
on the object.
Having said that, there is of course also no guarantee that the finalizer is called immediately (it might be called much later or not at all).
You either should explicitly call Dispose
or make use of the using
-statement so that your objects get properly disposed. As a safety net, you can still call Dispose
from the finalizer. In fact, that's a best practice also demonstrated by the example in MSDN.
A good read on the topic is Raymond Chen's post:
Upvotes: 3
Reputation: 68640
There is no* way to determine when the Garbage Collector will collect your object and call its finalizer (and, following the logic in your code, the Dispose
method).
Here's a good example of how unpredictable garbage collection is: http://ericlippert.com/2013/06/10/construction-destruction/
And even when the GC kicks in and collects the first generation of objects, your instance of PricingEnvironment
will survive the first collection and be put on the finalization queue instead.
You should dispose of your objects deterministically, by either calling Dispose
explicitly or using a using
block.
*You can actually force it with GC.Collect()
, but you shouldn't do that.
Upvotes: 0
Reputation: 1410
While computers are by definition deterministic, when allocated memory is released, is entirely up to the garbage collector of the implementation of the language. Setting it null will of cause decrease the reference count to the allocated memory, but that would happen in any case when the end of scope is reached.
Upvotes: 0