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. What makes a class IDisposable?

What makes a class IDisposable?

Scheduled Pinned Locked Moved Managed C++/CLI
csharpc++visual-studioquestion
32 Posts 6 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.
  • M mid 5741

    Are you being purposefully daft? I understand what's going on; I'm arguing that "C# does not have destructors" is an untrue statement. I'm not repudiating the mechanics. Dispute this: The C# language specification allows for the definition of destructors for class types.

    I Offline
    I Offline
    iddqd515
    wrote on last edited by
    #21

    From: http://en.wikipedia.org/wiki/Destructor\_(computer\_science) In object-oriented programming, a destructor (sometimes shortened to dtor) is a method which is automatically invoked when the object is destroyed. Its main purpose is to clean up and to free the resources which were acquired by the object along its life cycle and unlink it from other objects or resources invalidating any references in the process. The use of destructors is key to the concept of RAII. How in C# do you declare such a thing? A finalizer is not automatically invoked when the object is destroyed deterministically. It is nondeterministically called by the GC at some point in the future. Most important, in no way does a finalizer enable the RAII pattern. Take a FileStream class which encapsulates a resource in C#. Declare a finalizer for it. When an instance of a FileStream class goes out of the scope the finalizer is not called then. You do not know when it is called. Furthermore, even if the GC does a collect and there are no roots in the code to the object, the simple existence of the finalizer counts as a root and can cause the FileStream object to be promoted into the next generation and not collected by the GC until the next collect cycle (who knows when that will be). So while your FileStream object may have gone out of scope ages ago, by not calling Dispose and assuming the finalizer will close the FileStream, you have potentially caused a resource leak. The next function call that assumes the file you previously had used with the FileStream object is closed may throw an exception because you were relying on the garbage collector to nondeterministically release a critical resource. On the other hand, a destructor in C++/CLI will be called the moment the FileStream goes out of scope (assuming you declared the object with stack semantics and not gcnew). Then in the destructor you make sure there is a call to Dispose and you ensure that the resource is released immediately. You don't need a try/finally and you don't need to explicitly call Dispose and nor does anyone who uses your class in the future. The destructor incurs no performance penalty during allocation or deallocation like a finalizer does either. There's no way to declare such a function in C#. To say 'I'm not repudiating the mechanics' therefore C# has destructors is completely wrong. The mechanics are exa

    M M 2 Replies Last reply
    0
    • I iddqd515

      From: http://en.wikipedia.org/wiki/Destructor\_(computer\_science) In object-oriented programming, a destructor (sometimes shortened to dtor) is a method which is automatically invoked when the object is destroyed. Its main purpose is to clean up and to free the resources which were acquired by the object along its life cycle and unlink it from other objects or resources invalidating any references in the process. The use of destructors is key to the concept of RAII. How in C# do you declare such a thing? A finalizer is not automatically invoked when the object is destroyed deterministically. It is nondeterministically called by the GC at some point in the future. Most important, in no way does a finalizer enable the RAII pattern. Take a FileStream class which encapsulates a resource in C#. Declare a finalizer for it. When an instance of a FileStream class goes out of the scope the finalizer is not called then. You do not know when it is called. Furthermore, even if the GC does a collect and there are no roots in the code to the object, the simple existence of the finalizer counts as a root and can cause the FileStream object to be promoted into the next generation and not collected by the GC until the next collect cycle (who knows when that will be). So while your FileStream object may have gone out of scope ages ago, by not calling Dispose and assuming the finalizer will close the FileStream, you have potentially caused a resource leak. The next function call that assumes the file you previously had used with the FileStream object is closed may throw an exception because you were relying on the garbage collector to nondeterministically release a critical resource. On the other hand, a destructor in C++/CLI will be called the moment the FileStream goes out of scope (assuming you declared the object with stack semantics and not gcnew). Then in the destructor you make sure there is a call to Dispose and you ensure that the resource is released immediately. You don't need a try/finally and you don't need to explicitly call Dispose and nor does anyone who uses your class in the future. The destructor incurs no performance penalty during allocation or deallocation like a finalizer does either. There's no way to declare such a function in C#. To say 'I'm not repudiating the mechanics' therefore C# has destructors is completely wrong. The mechanics are exa

      M Offline
      M Offline
      mid 5741
      wrote on last edited by
      #22

      iddqd515 wrote:

      How in C# do you declare such a thing?

      ~Class()

      I 1 Reply Last reply
      0
      • M mid 5741

        iddqd515 wrote:

        How in C# do you declare such a thing?

        ~Class()

        I Offline
        I Offline
        iddqd515
        wrote on last edited by
        #23

        Well like I said then, make sure to declare ~Class() in all your C# classes and don't bother explicitly invoking Dispose. I'm sure you'll find it works fantastically. Also make sure to take advantage of finalizers to declare reference classes in C# with stack semantics. -- modified at 15:30 Monday 13th August, 2007

        M 1 Reply Last reply
        0
        • I iddqd515

          Well like I said then, make sure to declare ~Class() in all your C# classes and don't bother explicitly invoking Dispose. I'm sure you'll find it works fantastically. Also make sure to take advantage of finalizers to declare reference classes in C# with stack semantics. -- modified at 15:30 Monday 13th August, 2007

          M Offline
          M Offline
          mid 5741
          wrote on last edited by
          #24

          No need to get pissy. As I said earlier, I'm not advocating the use of what the language itself calls (or, apparently, used to call) a destructor; I'm just claiming that such a beast exists. From the C# Language Specification: [Note: In the previous version of this standard, what is now referred to as a "finalizer" was called a "destructor". Experience has shown that the term "destructor" caused confusion and often resulted to incorrect expectations, especially to programmers knowing C++. In C++, a destructor is called in a determinate manner, whereas, in C#, a finalizer is not. To get determinate behavior from C#, one should use Dispose. end note]

          I 1 Reply Last reply
          0
          • I iddqd515

            I'm pretty sure we've said the same thing. However... You say destructors are not called on an object allocated on the managed heap which isn't strictly true. If you allocate it on the managed heap with gcnew then yes the destructor is never called if you don't manually call delete. However, if you instantiate the ref class object with stack semantics then the destructor is called implicitly when the object goes out of scope (even though underneath its still allocated on the managed heap like all ref class objects). This is the critical addition to C++/CLI (vs MC++) that allowed for RAII style coding like native C++. Michael was claiming this is not the case (as it is in native C++) and that the finalizer is what is called, which is not correct. The finalizer will be called eventually either way if you define one, but the way things work is obviously much different than what a destructor provides. The confusion is that in C# when you declare ~Class1() this is actually mapped to the finalizer (Dispose(false)) in the dispose pattern. C# has no concept of destructors like C++ or C++/CLI even though the semantics there look like you're declaring a destructor. In C++/CLI you accomplish the same thing by declaring !Class1() which more properly distinguishes the finalizer from the destructor. Then declaring ~Class1() in C++/CLI does a very different thing than ~Class1() in C#. That's why in C# you need to explicitly call Dispose() in a finally block or use a using block with things like FileWriter objects to ensure there is no resource leak. C++/CLI's destructor semantics provide the handy native C++ style, FileWriter fw; which will automatically be disposed of properly when it goes out of scope (deterministically).

            M Offline
            M Offline
            Mark Salsbery
            wrote on last edited by
            #25

            iddqd515 wrote:

            in C# when you declare ~Class1() this is actually mapped to the finalizer (Dispose(false)) in the dispose pattern.

            Dispose() isn't the finalizer...Finalize() is, right? Regardless, C++ does the same - the destructor becomes Dispose() (quite literally, as Michael's original warning message stated). In C++ the Destructor is explicitly called when a stack-based syntax managed object goes out of scope, the destructor is called directly, a managed heap object is explicitly deleted with delete, or another language calls Dispose() on an object. If the class implements a finalizer then that needs to be (at least SHOULD be) called from the destructor.  The compiler takes care of calling SuppressFinalize so the finalizer will not be called again by the GC. Isn't that the same as the C# (and probably VB) Dispose/Finalize pattern? Mark

            Mark Salsbery Microsoft MVP - Visual C++ :java:

            1 Reply Last reply
            0
            • M mid 5741

              No need to get pissy. As I said earlier, I'm not advocating the use of what the language itself calls (or, apparently, used to call) a destructor; I'm just claiming that such a beast exists. From the C# Language Specification: [Note: In the previous version of this standard, what is now referred to as a "finalizer" was called a "destructor". Experience has shown that the term "destructor" caused confusion and often resulted to incorrect expectations, especially to programmers knowing C++. In C++, a destructor is called in a determinate manner, whereas, in C#, a finalizer is not. To get determinate behavior from C#, one should use Dispose. end note]

              I Offline
              I Offline
              iddqd515
              wrote on last edited by
              #26

              So that right there says 'sorry we incorrectly used to refer to this as a destructor. We realized it was confusing because its really not a destructor at all. To get destructor like behavior in C# use the Dispose method.' Therefore, C# has no destructors. And even in the past, it only had them in name, not function. But its been awhile since anyone referred to them as destructors since its blatantly confusing, especially with the introduction of C++/CLI in '05.

              1 Reply Last reply
              0
              • I iddqd515

                From: http://en.wikipedia.org/wiki/Destructor\_(computer\_science) In object-oriented programming, a destructor (sometimes shortened to dtor) is a method which is automatically invoked when the object is destroyed. Its main purpose is to clean up and to free the resources which were acquired by the object along its life cycle and unlink it from other objects or resources invalidating any references in the process. The use of destructors is key to the concept of RAII. How in C# do you declare such a thing? A finalizer is not automatically invoked when the object is destroyed deterministically. It is nondeterministically called by the GC at some point in the future. Most important, in no way does a finalizer enable the RAII pattern. Take a FileStream class which encapsulates a resource in C#. Declare a finalizer for it. When an instance of a FileStream class goes out of the scope the finalizer is not called then. You do not know when it is called. Furthermore, even if the GC does a collect and there are no roots in the code to the object, the simple existence of the finalizer counts as a root and can cause the FileStream object to be promoted into the next generation and not collected by the GC until the next collect cycle (who knows when that will be). So while your FileStream object may have gone out of scope ages ago, by not calling Dispose and assuming the finalizer will close the FileStream, you have potentially caused a resource leak. The next function call that assumes the file you previously had used with the FileStream object is closed may throw an exception because you were relying on the garbage collector to nondeterministically release a critical resource. On the other hand, a destructor in C++/CLI will be called the moment the FileStream goes out of scope (assuming you declared the object with stack semantics and not gcnew). Then in the destructor you make sure there is a call to Dispose and you ensure that the resource is released immediately. You don't need a try/finally and you don't need to explicitly call Dispose and nor does anyone who uses your class in the future. The destructor incurs no performance penalty during allocation or deallocation like a finalizer does either. There's no way to declare such a function in C#. To say 'I'm not repudiating the mechanics' therefore C# has destructors is completely wrong. The mechanics are exa

                M Offline
                M Offline
                Mark Salsbery
                wrote on last edited by
                #27

                iddqd515 wrote:

                On the other hand, a destructor in C++/CLI will be called the moment the FileStream goes out of scope (assuming you declared the object with stack semantics and not gcnew). Then in the destructor you make sure there is a call to Dispose

                That may be where my confusion with your statements is coming from. That sounds like managed extensions.  In VS 2005, you can't call Dispose() - the compiler won't let you.  This is now done implicitly with the destructos symantics. Mark

                Mark Salsbery Microsoft MVP - Visual C++ :java:

                I 1 Reply Last reply
                0
                • M Mark Salsbery

                  iddqd515 wrote:

                  On the other hand, a destructor in C++/CLI will be called the moment the FileStream goes out of scope (assuming you declared the object with stack semantics and not gcnew). Then in the destructor you make sure there is a call to Dispose

                  That may be where my confusion with your statements is coming from. That sounds like managed extensions.  In VS 2005, you can't call Dispose() - the compiler won't let you.  This is now done implicitly with the destructos symantics. Mark

                  Mark Salsbery Microsoft MVP - Visual C++ :java:

                  I Offline
                  I Offline
                  iddqd515
                  wrote on last edited by
                  #28

                  Sorry, I was being ambiguous. All this Dispose talk and switching between C# and C++/CLI gets me mixed up occasionally. You're correct, I meant in the destructor a call to Dispose(true) is made. In any case, the important part (C++/CLI destructors are deterministic) is the same, while a C# finalizer is completely different due to its nondeterministic nature. Luckily I've never had to use MC++. *shudder* -- modified at 15:49 Monday 13th August, 2007

                  M 1 Reply Last reply
                  0
                  • I iddqd515

                    Sorry, I was being ambiguous. All this Dispose talk and switching between C# and C++/CLI gets me mixed up occasionally. You're correct, I meant in the destructor a call to Dispose(true) is made. In any case, the important part (C++/CLI destructors are deterministic) is the same, while a C# finalizer is completely different due to its nondeterministic nature. Luckily I've never had to use MC++. *shudder* -- modified at 15:49 Monday 13th August, 2007

                    M Offline
                    M Offline
                    Mark Salsbery
                    wrote on last edited by
                    #29

                    Cool.  I'm just making sure for my own clarification. I recently ported code from VS2003 and while I was ready for many of the changes, the Dispose stuff was a surprise.  I want to make sure I've got it clear in my head since I only used the documentation as a learnin' resource :) Cheers, Mark

                    Mark Salsbery Microsoft MVP - Visual C++ :java:

                    I 1 Reply Last reply
                    0
                    • M Mark Salsbery

                      Cool.  I'm just making sure for my own clarification. I recently ported code from VS2003 and while I was ready for many of the changes, the Dispose stuff was a surprise.  I want to make sure I've got it clear in my head since I only used the documentation as a learnin' resource :) Cheers, Mark

                      Mark Salsbery Microsoft MVP - Visual C++ :java:

                      I Offline
                      I Offline
                      iddqd515
                      wrote on last edited by
                      #30

                      Yeah its taken me over a month to really grasp the whole pattern and how it meshes with traditional C++ semantics. Its not helpful when you try to find stuff about the Dispose pattern and end up with C# examples mixing terms to create more confusion. On the plus side, now C++/CLI basically works just like you would expect native C++ to in most cases and you only need to worry about finalizers for classes with unmanaged members. Certainly an improvement over MC++ (as most things are).

                      1 Reply Last reply
                      0
                      • M Mark Salsbery

                        Michael Chapman wrote:

                        That just seems totally counterintuitive to using managed code.

                        Yes, but so is mixing native types and having destructors. The garbage collector will only cleanup managed objects if you don't specifically call a destructor. Since you don't need deterministic cleanup of your native object, the smart pointer is a good solution, since it provides the destructor/finalizer for you. Only if you needed deterministic cleanup of your native object would you need to implement a destructor and possibly a finalizer as shown in the article (although you do it implicitely with the smart pointer). Mark

                        Mark Salsbery Microsoft MVP - Visual C++ :java:

                        G Offline
                        G Offline
                        George L Jackson
                        wrote on last edited by
                        #31

                        Mark, You might also want to consider SafeHandle: http://blogs.msdn.com/bclteam/archive/2005/03/16/396900.aspx[^]

                        "We make a living by what we get, we make a life by what we give." --Winston Churchill

                        M 1 Reply Last reply
                        0
                        • G George L Jackson

                          Mark, You might also want to consider SafeHandle: http://blogs.msdn.com/bclteam/archive/2005/03/16/396900.aspx[^]

                          "We make a living by what we get, we make a life by what we give." --Winston Churchill

                          M Offline
                          M Offline
                          Mark Salsbery
                          wrote on last edited by
                          #32

                          Interesting!  Thanks for the link George! Mark

                          Mark Salsbery Microsoft MVP - Visual C++ :java:

                          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