Wednesday, 23 July 2008

IDisposable in C++/CLI

A formula for a disposable class in C++/CLI

ref class MyClass : Base {

  int disposed;
  ManagedResource^ managed_resource;
  ManagedResource auto_managed_resource;
  void* unmanaged_resource;

  !MyClass() { free(unmanaged_resource); }

public:
  ~MyClass() {
    if (System.Threading.Interlocked.
            CompareExchange(disposed, 1, 0))
      return;

    managed_resource.Dispose();
    this->!MyClass();
  }
};

This class implements IDisposable, disposes both managed resources and the unmanaged resource. If it were a derived class it would correctly dispose and finalise its base class automatically (C++/CLI does that for you).

Note that reference classes can be defined without the carat "^" and they will be disposed when they go out of scope like in real C++.
Rules of thumb:
  1. Only release unmanaged resources in !MyClass
  2. Never perform any slow operations in !MyClass or which might depend on ordering with respect to any other part of the program. It would be agood idea to not call any dispose methods.
  3. Do not allow a reference to this to be saved somewhere from !MyClass. It would be a good idea to not use keyword "this" in !MyClass to avoid it being saved in a function that you use but don't know the implementation.
  4. Do not call a base class !Base or ~Base - let the compiler add them for you.
  5. Treat all breaches of these rules of thumb with suspicion.

No comments: