Question

I want to make a global vector of my own object class called "Person". However, the compiler says that

    error C2039: '{dtor}' : is not a member of 'System::IDisposable'
1>        c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll : see declaration of 'System::IDisposable'

So I looked up how to implement IDisposable (which I now know is used primarily for unmanaged resources) but still can't seem to implement it with the following:

ref class Globals : System::IDisposable
{  
public: 
  static cliext::vector<Person^> person_data = gcnew cliext::vector<Person^>;
    void Dispose()
    {
         delete person_data;
    }
}; 

The 2 errors I get are:

error C2605: 'Dispose' : this method is reserved within a managed class
1>        did you intend to define a destructor?
error C3766: 'Globals' must provide an implementation for the interface method 'void System::IDisposable::Dispose(void)'
1>        c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll : see declaration of 'System::IDisposable::Dispose'
Was it helpful?

Solution

From C++/CLI in Action The C++/CLI Dispose pattern has these rules (paraphrased):

  • If a class has a finalizer or a destructor the compiler generates Dispose(bool) that will call either the finalizer or destructor based on the bool value.
  • If it has just a d'tor (~type) then the compiler calls Dispose(true) so the d'tor is called.
  • If it has just a finalizer (!type) then the compiler calls Dispose(false) so the finalizer is called

Also for the second rule: The compiler will implement the IDisposable interface for you (by generating Dispose()). It then uses SuppressFinalize to make sure the finalizer isn't called.

I did this to your code and the only way I could get it to compile was to make person_data a instance member. The error i got when it was static was error C2039: '{dtor}' : is not a member of 'System::IDisposable' which doesn't make much sense.

Also, do you even need to delete the person_data vector since is a managed object? Maybe you do but I haven't used the cliext enough to say.

Edit Perhaps the first paragraph of this article has the answer (emphasis mine):

When you declare a member variable as static and when the application starts, the compiler creates a copy of that member. This member would be maintained by the compiler while the program is running. If you declare an instance of a class, like the above vehicle variable, the static member is not part of the object: the compiler creates and maintains the static member, whether you use it or not, whether you declare a class variable or not.

OTHER TIPS

You don't have to explicitly derive from IDisposable. Following the MSDN doco, use the following pattern:

ref class Globals
{
public:
    static cliext::vector<Person^> person_data = gcnew cliext::vector<Person^>;
    !Globals() // finalizer
    {
        delete person_data;
    {
protected:
    ~Globals() // destructor calls finalizer
    {
        this->!Globals();
    }
};

Use a destructor. In C++/CLI ~ClassName() is Dispose() and !ClassName() is equivalent to C#'s ~ClassName(). In your case:

ref class Globals : System::IDisposable
{  
public: 
    static cliext::vector<Person^> person_data = gcnew cliext::vector<Person^>;
    void ~Globals()
    {
        delete person_data;
    }
}; 

You don't need to implement Dispose() yourself, either directly or via a destructor. The implicitly-generated destructor already destroys all member objects. The IDisposable interface will be added automatically, don't mention it explicitly.

Next, you need to make up your mind whether person_data is a handle (which has to be set to an instance created with gcnew) or member object semantics (like stack semantics, the constructor is automatically called by the constructor of the parent object, the destructor called automatically when the lifetime of the parent object ends, and you use "." instead of "->" to access members).

Also, are you sure you want one copy of person_data shared between all instances of "Globals", but destroyed by the first instance to be disposed, leaving any other instances holding an invalid reference (reference to disposed object)? It looks like you're trying to use a Singleton anti-pattern here, is that correct?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top