Using Invariant for IDisposable

Consider the following IDisposable class:

 class MyClass : IDisposable { public bool IsDisposed { get; private set; } = false; public void Dispose() { IsDisposed = true; } } 

Each method of this class, including Dispose() , should start with a test as follows:

 if (IsDisposed) { throw new ObjectDisposedException(...); } 

Since this is tedious and is repeated to write this in all methods, I would like to use the contract invariant:

 public class MyClass : IDisposable { ... [ContractInvariantMethod] private void objectInvariant() { Contract.Invariant(!IsDisposed) } ... } 

However, this only ensures that IsDisposed is false at the end of each public method, excluding Dispose() .

After calling Dispose() validation should be performed at the beginning of each method (including Dispose() ). Otherwise, the obejct will be in an invalid state during the start of the method, which will potentially lead to complex errors.

Therefore, contract invariants are not really applicable for IDisposable . Or am I missing something?

Is it possible to make invariants also be used as preconditions or do I really need to write the same precondition ( !IsDisposed ) to all methods manually?

+6
source share
1 answer

You seem to be mistaken in invariants. From the documentation:

Object invariants are conditions that must be true for each instance of a class whenever this object is visible to the client.

(My emphasis) Your object can be clearly visible to the client after calling Dispose , which makes the object "invalid". But actually this is a valid state for your object with IsDisposed == true .

You are really looking for preconditions.

+4
source

All Articles