views:

179

answers:

1

Consider the below:

#include <iostream>

public ref class TestClass {
public:
    TestClass() { std::cerr << "TestClass()\n"; }
    ~TestClass() { std::cerr << "~TestClass()\n"; }
};

public ref class TestContainer {
public:
    TestContainer() : m_handle(gcnew TestClass) { }

private:
    TestClass^ m_handle;
};

void createContainer() {
    TestContainer^ tc = gcnew TestContainer();
        // object leaves scope and should be marked for GC(?)
}


int main() {
    createContainer();

    // Manually collect.
    System::GC::Collect();
    System::GC::WaitForPendingFinalizers();

    // ... do other stuff

    return 0;
}

My output is simply: TestClass()

I never get ~TestClass(). This is a simplification of an issue I am having in production code, where a list of handles is being cleared and repopulated multiple times, and the handle destructors are never being called.

What am I doing wrong?

Sincerely, Ryan

+3  A: 
~TestClass()

declares a Dispose function.

!TestClass()

would declare a finaliser (the equivalent of C#'s ~TestClass) which gets called on a gc collection (although that's not guaranteed).

James Hopkin
Thank you very much, I did not realize this was the case.
Ryan
yeah, unfortunately so. Its a stupid design decision.
gbjbaanb
And I think C++/CLI will make sure TestClass implements IDispose when you add ~TestClass(), so other .NET languages will understand it.
MSalters
It's unfortunate that `~TestClass()` means different things in C# and C++, but Dispose functions really are the closest parallel to a C++ destructor.
James Hopkin