I got stuck in the weeds of how IDisposable
and the GarbageCollector
work.
Suppose you have an IDisposable
object, which doesn't actually have an resources that it's holding onto (but the Dispose()
method is going to do something when called). And suppose you declare it in the head of a using
block, but don't actually interact with the object over the course of the block.
What guarantees do I have about how GarbageCollection
will operate?
i.e.
using(new MyConceptuallyDisposableObject())
{
DoSomeWork();
await DoSomeAsyncWork();
}//PointX
Note that:
- MyConceptuallyDisposableObject doesn't declare a finaliser / destructor.
- (Assume that developers will never forget to
using
`.Dispose()` my object)
- (Assume that developers will never forget to
- MyConceptuallyDisposableObject doesn't call
GC.SuppressFinalise(this)
anywhere.
Am I guaranteed that the object
that I constructed will:
- Will not have
.Dispose()
called on it beforePointX
? - Will have
.Dispose()
called on it at exactlyPointX
? - Will not get GarbageCollected/Finalised at any point before
PointX
? - Will not get GarbageCollected/Finalised before it has had
.Dispose()
called on it?
Suppose I then change my code to make MyConceptuallyDisposableObject
call GC.SuppressFinalise(this)
in its constructor. (Bearing in mind that there isn't any Destructor or Finaliser)
- Does that change any of the answers to the specific questions above?
- Does anything change in general, then?
- Does it mean that the
GC
never cleans up my object at all and I'll end up with a memory leak?
*Context:*
Posted for those who are inevitably curious, but PLEASE don't answer based suggesting other ways to achieve this or that I shouldn't do this. Right now, I'm much more invested in understanding the guts of the above concepts in their abstract sense, not discussing whether my initial attempt was sensible.
I want to write a DisposableAction()
class, which accepts 2 Action
s. One to perform when you construct it, and one to perform when you Dispose()
it.
I thought I knew all the answers to the above (and that they were "Yes", "Yes", "Yes", "Yes", "No", "Almost nothing unless you're incredibly perf-sensitive", and "No".), but I've been trying to diagnose a bug which appears to contradict these beliefs.
IDisposable
and garbage collection are unrelated, except for the one situation where an object implements a finalizer that happens to call.Dispose()
.Unless you know for sure, 100%, and explicitly, that an object has a finalizer that calls
.Dispose()
then you must call.Dispose()
explicitly (or with ausing
) to ensure the object is disposed.The answers to your questions: