Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Managed C++/CLI
  4. Implementing IDisposable

Implementing IDisposable

Scheduled Pinned Locked Moved Managed C++/CLI
csharpc++helpquestion
8 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • V Offline
    V Offline
    VizOne
    wrote on last edited by
    #1

    Hi there! I am currently currently working .net classes that implement IDisposable following the msdn-guidelines, but I have a problem I hope you can help me with: Let's say these are my classes: public __gc class B : public IDisposable { public: // Destructor calls Dispose(bool) ~B() { Dispose(false); } // Implements interface virtual void Dispose() { Dispose(true); GC::SuppressFinalize(this); } // this is the workhorse, it handles manual and finalizer // disposing differently as recommended by MS virtual void Dispose(bool arg) { /* whatever */ } }; public __gc class D : public B { public: // overrides Dispose(bool), but ultimatly calls B::Dispose(bool) virtual void Dispose(bool arg) { /* whatever */ B::Dispose(arg); } }; Looks nice, but does not work :( I can't do something like that: D* d = new D(); d->Dispose(); as the hide-by-name convention does not allow that. In native C++ I could use a using declaration: public __gc class D : public B { using B::Dispose; /*...*/ }; and everything was fine. However, this is not allowed in .net. Nevertheless this implementation of IDispose is used throughout the framework. How did MS do this? Did I miss something? Is it only possible in C#? Thanks in advance. - Andre (VizOne) Loker

    P 1 Reply Last reply
    0
    • V VizOne

      Hi there! I am currently currently working .net classes that implement IDisposable following the msdn-guidelines, but I have a problem I hope you can help me with: Let's say these are my classes: public __gc class B : public IDisposable { public: // Destructor calls Dispose(bool) ~B() { Dispose(false); } // Implements interface virtual void Dispose() { Dispose(true); GC::SuppressFinalize(this); } // this is the workhorse, it handles manual and finalizer // disposing differently as recommended by MS virtual void Dispose(bool arg) { /* whatever */ } }; public __gc class D : public B { public: // overrides Dispose(bool), but ultimatly calls B::Dispose(bool) virtual void Dispose(bool arg) { /* whatever */ B::Dispose(arg); } }; Looks nice, but does not work :( I can't do something like that: D* d = new D(); d->Dispose(); as the hide-by-name convention does not allow that. In native C++ I could use a using declaration: public __gc class D : public B { using B::Dispose; /*...*/ }; and everything was fine. However, this is not allowed in .net. Nevertheless this implementation of IDispose is used throughout the framework. How did MS do this? Did I miss something? Is it only possible in C#? Thanks in advance. - Andre (VizOne) Loker

      P Offline
      P Offline
      Paul Selormey
      wrote on last edited by
      #2

      Try this template:

      public __gc class Hello : public System::IDisposable
      {
      public:
      Hello(void)
      {
      }

      virtual ~Hello(void)
      {
      	Dispose(false);
      }
      
      ////////////////////////////////////////////////////////////////////////////
      // The System::IDisposable interface implementations
      
      void Dispose()
      {
      	Dispose(true);
      }
      

      protected:
      void Dispose(bool disposing)
      {
      // Normally clean up here....

      	if (disposing)
      	{
      		System::GC::SuppressFinalize(this);
      	}
      }
      

      };

      Best regards, Paul. Jesus Christ is LOVE! Please tell somebody.

      V 1 Reply Last reply
      0
      • P Paul Selormey

        Try this template:

        public __gc class Hello : public System::IDisposable
        {
        public:
        Hello(void)
        {
        }

        virtual ~Hello(void)
        {
        	Dispose(false);
        }
        
        ////////////////////////////////////////////////////////////////////////////
        // The System::IDisposable interface implementations
        
        void Dispose()
        {
        	Dispose(true);
        }
        

        protected:
        void Dispose(bool disposing)
        {
        // Normally clean up here....

        	if (disposing)
        	{
        		System::GC::SuppressFinalize(this);
        	}
        }
        

        };

        Best regards, Paul. Jesus Christ is LOVE! Please tell somebody.

        V Offline
        V Offline
        VizOne
        wrote on last edited by
        #3

        This was what I have done. However, I can't call Dipose() on an object of the derived class because it is hidden-by-name. I guess this template is only implemantable in C#, so I simply renamed Dispose(bool) to InternalDispose(bool), which works fine for me. Nevertheless thanks for your answer. - Andre

        P 1 Reply Last reply
        0
        • V VizOne

          This was what I have done. However, I can't call Dipose() on an object of the derived class because it is hidden-by-name. I guess this template is only implemantable in C#, so I simply renamed Dispose(bool) to InternalDispose(bool), which works fine for me. Nevertheless thanks for your answer. - Andre

          P Offline
          P Offline
          Paul Selormey
          wrote on last edited by
          #4

          The Dispose(Boolean) has nothing to do with .NET. The interface IDisposable only defines Dispose(), so you are doing anything wrong here. The Dispose(Boolean) is defined as either private or protected, so external classes are not supposed to access it. See the doc for IDisposable, there is an MC++ example given there to confirm your approach. Best regards, Paul. Jesus Christ is LOVE! Please tell somebody.

          V 1 Reply Last reply
          0
          • P Paul Selormey

            The Dispose(Boolean) has nothing to do with .NET. The interface IDisposable only defines Dispose(), so you are doing anything wrong here. The Dispose(Boolean) is defined as either private or protected, so external classes are not supposed to access it. See the doc for IDisposable, there is an MC++ example given there to confirm your approach. Best regards, Paul. Jesus Christ is LOVE! Please tell somebody.

            V Offline
            V Offline
            VizOne
            wrote on last edited by
            #5

            Yes, I *do* know. And I don't want to access Dispose(bool), but Dispose(). I give you an example of what I mean: public __gc class B : public IDisposable { public: virtual ~B() { Dispose(false); } virtual void Dispose() { Dispose(true); } protected: virtual void Dispose(bool arg) { /* Clean up */ } }; public __gc class D : public B { protected: virtual void Dispose(bool arg) { /* Clean up */ // call base classes implementation B::Dispose(arg); } }; int _tmain(void) { D * d = new D(); d->Dispose(); return 0; } This is implemented as suggested in MSDN, isn't it? However, it does not work. d->Dispose() generates a C2660 saying that Dispose does not accept 0 parameters. This error is obviously caused by the fact that Dispose() is hidden-by-name. I could use d->B::Dispose() but this looks ugly to me, so I renamed Dispose(bool) to InternalDispose(bool). Hope I could explain what I meant. - Andre

            P 1 Reply Last reply
            0
            • V VizOne

              Yes, I *do* know. And I don't want to access Dispose(bool), but Dispose(). I give you an example of what I mean: public __gc class B : public IDisposable { public: virtual ~B() { Dispose(false); } virtual void Dispose() { Dispose(true); } protected: virtual void Dispose(bool arg) { /* Clean up */ } }; public __gc class D : public B { protected: virtual void Dispose(bool arg) { /* Clean up */ // call base classes implementation B::Dispose(arg); } }; int _tmain(void) { D * d = new D(); d->Dispose(); return 0; } This is implemented as suggested in MSDN, isn't it? However, it does not work. d->Dispose() generates a C2660 saying that Dispose does not accept 0 parameters. This error is obviously caused by the fact that Dispose() is hidden-by-name. I could use d->B::Dispose() but this looks ugly to me, so I renamed Dispose(bool) to InternalDispose(bool). Hope I could explain what I meant. - Andre

              P Offline
              P Offline
              Paul Selormey
              wrote on last edited by
              #6

              VizOne wrote: Hope I could explain what I meant. Yeah, but you are missing the point main here. VizOne wrote: I could use d->B::Dispose() but this looks ugly to me, so I renamed Dispose(bool) to InternalDispose(bool). Add some output to the D::Dispose or D::InternalDispose to see if it is being called! A better picture is cast the D pointer to IDisposable, it will compile, but similar to the above you end up calling B::Dispose, it is similar to your d->B::Dispose() syntax.

              int _tmain(void)
              {
              D * d = new D();
              __try_cast(d)->Dispose();
              return 0;
              }

              The best way is to implement the same interface in D, since you will not get the expected result by renaming. Also, you trying to convert the IDisposable::Dispose() to virtual, it will compile but will not act as virtual method. Best regards, Paul. Jesus Christ is LOVE! Please tell somebody.

              V 1 Reply Last reply
              0
              • P Paul Selormey

                VizOne wrote: Hope I could explain what I meant. Yeah, but you are missing the point main here. VizOne wrote: I could use d->B::Dispose() but this looks ugly to me, so I renamed Dispose(bool) to InternalDispose(bool). Add some output to the D::Dispose or D::InternalDispose to see if it is being called! A better picture is cast the D pointer to IDisposable, it will compile, but similar to the above you end up calling B::Dispose, it is similar to your d->B::Dispose() syntax.

                int _tmain(void)
                {
                D * d = new D();
                __try_cast(d)->Dispose();
                return 0;
                }

                The best way is to implement the same interface in D, since you will not get the expected result by renaming. Also, you trying to convert the IDisposable::Dispose() to virtual, it will compile but will not act as virtual method. Best regards, Paul. Jesus Christ is LOVE! Please tell somebody.

                V Offline
                V Offline
                VizOne
                wrote on last edited by
                #7

                Paul Selormey wrote: Also, you trying to convert the IDisposable::Dispose() to virtual, it will compile but will not act as virtual method Well I am sure it *does* act as a virtual method. Excerpt from MSDN doc on managed c++: "The following features are supported for __gc interfaces: All methods of an interface are implicitly pure virtual. Neither the keyword virtual nor the suffix =0 is required on an interface method declaration, although both are allowed" Here is a small test in which I have included everything I mentioned so far. It works perfectly for me: public __gc class B : public IDisposable { public: virtual ~B() { Console::WriteLine("B::~B()"); InternalDispose(false); } virtual void Dispose() { Console::WriteLine("B::Dispose()"); InternalDispose(true); } protected: // renaming this function to InternalDispose solved my problem virtual void InternalDispose(bool arg) { Console::WriteLine("B::InternalDispose(bool)"); /* Clean up */ } }; public __gc class D : public B { public: // just to show that the function *is* virtual void Dispose() { Console::WriteLine("D::Dispose()"); B::Dispose(); } protected: void InternalDispose(bool arg) { Console::WriteLine("D::InternalDispose(bool)"); /* Clean up */ // call base classes implementation B::InternalDispose(arg); } }; int _tmain(void) { B * b = new D(); b->Dispose(); // as virtual as can be *g* } The output is (as expected) D::Dispose() B::Dispose() D::InternalDispose(bool) B::InternalDispose(bool) Of course, in my final version I will mark B::Dispose() as __sealed and throw away D::Dispose() - Andre

                P 1 Reply Last reply
                0
                • V VizOne

                  Paul Selormey wrote: Also, you trying to convert the IDisposable::Dispose() to virtual, it will compile but will not act as virtual method Well I am sure it *does* act as a virtual method. Excerpt from MSDN doc on managed c++: "The following features are supported for __gc interfaces: All methods of an interface are implicitly pure virtual. Neither the keyword virtual nor the suffix =0 is required on an interface method declaration, although both are allowed" Here is a small test in which I have included everything I mentioned so far. It works perfectly for me: public __gc class B : public IDisposable { public: virtual ~B() { Console::WriteLine("B::~B()"); InternalDispose(false); } virtual void Dispose() { Console::WriteLine("B::Dispose()"); InternalDispose(true); } protected: // renaming this function to InternalDispose solved my problem virtual void InternalDispose(bool arg) { Console::WriteLine("B::InternalDispose(bool)"); /* Clean up */ } }; public __gc class D : public B { public: // just to show that the function *is* virtual void Dispose() { Console::WriteLine("D::Dispose()"); B::Dispose(); } protected: void InternalDispose(bool arg) { Console::WriteLine("D::InternalDispose(bool)"); /* Clean up */ // call base classes implementation B::InternalDispose(arg); } }; int _tmain(void) { B * b = new D(); b->Dispose(); // as virtual as can be *g* } The output is (as expected) D::Dispose() B::Dispose() D::InternalDispose(bool) B::InternalDispose(bool) Of course, in my final version I will mark B::Dispose() as __sealed and throw away D::Dispose() - Andre

                  P Offline
                  P Offline
                  Paul Selormey
                  wrote on last edited by
                  #8

                  Nothing new, just re-implementing IDisposable to create the impression of a virtual method (in which case you do not have to use the "Internal" attachment) - have fun. Best regards, Paul. Jesus Christ is LOVE! Please tell somebody.

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups