2

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? :)

Community
  • 1
  • 1
Sarien
  • 6,647
  • 6
  • 35
  • 55
  • 2
    Implement IDisposable interface + use using(var a = new CLoadingScope()) that will call destructor... – Sergejs May 13 '13 at 10:53
  • @Sergejs I don't think using directives are allowed in C++/CLI. – Sarien May 13 '13 at 10:59
  • hmm, sorry. This is how it works in C#. Then, I believe you have to call destructor manually. – Sergejs May 13 '13 at 11:04
  • For a deeper understanding of when dispose is called read this SO post http://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 http://stackoverflow.com/questions/1987251/manually-destroy-c-sharp-objects – Paul Zahra May 13 '13 at 11:17
  • Furthermore when an object is disposed of it is only queued for GC, which will happen 'later' – Paul Zahra May 13 '13 at 11:21
  • @PaulZahra I understand what to do in C# but in C++/CLI I cannot use using directives and Dispose is not called when the object goes out of scope. I simply don't see how to do RAII in this case. – Sarien May 13 '13 at 11:47

2 Answers2

2

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
Matt Smith
  • 17,026
  • 7
  • 53
  • 103
  • The C# class had been written by another dev and I simply missed that the interface inheritance was missing. Thanks for pointing it out! – Sarien May 13 '13 at 13:23
0

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()

Paul Zahra
  • 9,522
  • 8
  • 54
  • 76
  • Calling it explicitly somewhat defeats the purpose of RAII of making it work in the presence of exceptions. :/ – Sarien May 13 '13 at 13:00