2
votes

I have a C# object that is resposible for a ressource which looks like this:

  public sealed class CLoadingScope
  {
    private bool isDisposed;

    public CLoadingScope()
    {}

    ~CLoadingScope()
    {
      // must be disposed otherwise it is used incorrectly
      if (!isDisposed)
      {
        throw new ApplicationException("RAII object has not been disposed");
      }
    }

    public void Dispose()
    {
      // CLEANUP CODE HERE […]
      isDisposed = true;
      GC.SuppressFinalize(this);
    }
  };

I am using this in some C++/CLI code like this:

{
  CLoadingScope scope;
  // CODE THAT USES THE RESSOURCE HERE […]
}

But this results in the Exception being thrown. I was expecting this to work because Dispose is the destructor of C# classes and stack objects are destroyed at the end of their scope. At least that's how I interpreted the answer to this question. With all the naming and usage confusion of finalizers and destructors in C#, C++ and C++/CLI I assume I mixed up something. Can anybody tell me what? :)

2
Implement IDisposable interface + use using(var a = new CLoadingScope()) that will call destructor...Sergejs
@Sergejs I don't think using directives are allowed in C++/CLI.Sarien
hmm, sorry. This is how it works in C#. Then, I believe you have to call destructor manually.Sergejs
For a deeper understanding of when dispose is called read this SO post stackoverflow.com/questions/2871888/dispose-when-is-it-called and for what may be more of a definitive answer for you read this SO post stackoverflow.com/questions/1987251/…Paul Zahra
Furthermore when an object is disposed of it is only queued for GC, which will happen 'later'Paul Zahra

2 Answers

2
votes

If I understand correctly, you have authored this class in C#, and are using it from C++/CLI.

You are correct that C++/CLI will automatically call Dispose for you--but that's only if the class you are dealing with implements IDisposable. In your case, your class does not implement IDisposable, and thus, Dispose in this case is just a normal method.

Change your class as follows:

public sealed class CLoadingScope : IDisposable
0
votes

Hope this helps:

Add a destructor which will make c++ /cli automagically inherit IDisposable.

Then cast to IDisposable to access the Dispose method

((IDisposable)obj).Dispose();

P.S. With regards to C# Dispose() is called with a using statement or of course manually, otherwise it doesn't get called automatically, not sure why the using equivalent in C++/CLI isn't calling Dispose()