Consider the following IDisposable
class:
class MyClass : IDisposable
{
public bool IsDisposed { get; private set; } = false;
public void Dispose()
{
IsDisposed = true;
}
}
Every method in this class, including Dispose()
, should begin with a check like this:
if (IsDisposed)
{
throw new ObjectDisposedException(...);
}
Since it is tedious and repetitive to write this in all methods, I would like to use contract invariant:
public class MyClass : IDisposable
{
...
[ContractInvariantMethod]
private void objectInvariant()
{
Contract.Invariant(!IsDisposed)
}
...
}
However, this only ensures IsDisposed is false at the end of each public method, excluding Dispose()
.
Once Dispose()
is called, the check should be done at the beginning of each method (including Dispose()
). Otherwise the obejct will be in invalid state during the method run, potentially leading to difficult bugs.
Hence contract invariants are not really usable for IDisposable
. Or am I missing something?
Is it possible to force invaraiants to be also used as preconditions or do I really have to write the same precondition (!IsDisposed
) to all methods manually?
You seem to be misunderstanding invariants. From the documentation:
Object invariants are conditions that should be true for each instance of a class whenever that object is visible to a client.
(Emphasis mine)
Your object can very well be visible to a client after you called Dispose
, making the object "invalid". But it actually is a valid state for your object to have IsDisposed == true
.
You are really looking for Pre-Conditions.
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