Adding unmanaged / non managed member to managed class

Viewed 454

Thank you for your attention. I'm new to some VS2013 code which is a mixture of C++ plus some microsoft specific extensions. The code has a class like

ref class Foo {
    Bar^ bar_; // somewhere else, bar_ = gcnew Bar...
};

Now I'd need to add an unmanaged member, from online search it seems like I can do

ref class Foo {
    Bar ^ bar_;
    Unmanaged* ptr_; // somewhere else, ptr = new Unmanaged();
    ~Foo() {
        this->!Foo();
    }
    !Foo() {
        delete ptr_;
        // do I need anything to deal with bar_?
    }
};

The questions are:

1) is this finalizer/destructor the way to go?

2) do I need to write anything extra for bar_ now that I'm explicitly writing the finalizer/destructor?

3) are there cleaner way to do it?

1 Answers

1) is this finalizer/destructor the way to go?

Yes.

2) do I need to write anything extra for bar_

Nothing that is obvious from the snippets. But if the Bar class is disposable as well then you probably ought to add delete bar_; to the destructor. Not to the finalizer. And not if you passed the reference to other code so you can't be sure that this reference is the last one still using the Bar object.

3) are there cleaner way to do it?

No. There are other ways to do it. You could for example consider to not add the destructor. Having one gives the code that uses the class the burden of calling it. Typically that would be C# or VB.NET code, it would have to use the using statement or call Dispose() explicitly. Keep in mind that they often forget. Or don't have a good way to call it.

If such code is not expected to create a lot of instances of Foo and the Unmanaged class merely uses a bit of memory then the finalizer might well be good enough. Or if the Foo object is expected to live for the lifetime of the app, pretty common, then disposing is pointless. Even if it does use a lot of memory then GC::AddMemoryPressure() is a pretty nice alternative. Makes your class easier to use.

And you could consider wrapping the Unmanaged pointer in its own class so Foo doesn't need a finalizer anymore. Along the pattern of the SafeHandle classes in .NET, SafeBuffer is the closest match. That tends to be overkill however in a C++/CLI wrapper, delete failure in particular is nothing you want to hide.

But what you have gets the job done.

Related