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. Other Discussions
  3. Clever Code
  4. Call Dispose on anything

Call Dispose on anything

Scheduled Pinned Locked Moved Clever Code
question
44 Posts 11 Posters 57 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.
  • P PIEBALDconsult

    Writing a generic collection and want to dispose of items that implement IDisposable, but don't want to bother checking each item or type for IDisposable? Why not associate a bogus Dispose method with every class that doesn't already have one? public static void Dispose ( this object Object ){} :cool: (Just be careful of non-IDisposable classes that have a Dispose method anyway. :suss: )

    A Offline
    A Offline
    Andrew Rissing
    wrote on last edited by
    #2

    The only problem though with doing that is that you'll never reach the actual dispose method, unless you've reference it as the type that defines the dispose method. But then, if you're going to do that, you wouldn't need the above extension. Why not just create an extension method that does the following:

        public static void Dispose(this object Object)
        {
            IDisposable disposable;
    
            if ((disposable = (Object as IDisposable)) != null)
                disposable.Dispose();
        }
    
    P 1 Reply Last reply
    0
    • A Andrew Rissing

      The only problem though with doing that is that you'll never reach the actual dispose method, unless you've reference it as the type that defines the dispose method. But then, if you're going to do that, you wouldn't need the above extension. Why not just create an extension method that does the following:

          public static void Dispose(this object Object)
          {
              IDisposable disposable;
      
              if ((disposable = (Object as IDisposable)) != null)
                  disposable.Dispose();
          }
      
      P Offline
      P Offline
      PIEBALDconsult
      wrote on last edited by
      #3

      Because that won't be called for classes that have a public Dispose method anyway.

      G 1 Reply Last reply
      0
      • P PIEBALDconsult

        Because that won't be called for classes that have a public Dispose method anyway.

        G Offline
        G Offline
        Gideon Engelberth
        wrote on last edited by
        #4

        Actually, it would. The generic overloading rules I assume you are basing your position on only apply at source compile time. Since the actual type is not known at the time your generic collection (or whatever) is compiled, you would end up always calling the extension method. A simple example to demonstrate:

        Module Module1

        Sub Main()
            Dim di As New Disposer(Of Integer)(43)
            Dim dd As New Disposer(Of DisposableTest)(New DisposableTest)
        
            Console.WriteLine("Disposing Disposer(Of Integer)")
            di.Cleanup()
            Console.WriteLine("Disposing Disposer(Of DisposableTest)")
            dd.Cleanup()
        
            Dim dtemp As New DisposableTest()
            Console.WriteLine("Disposing DisposableTest")
            dtemp.Dispose()
        
            Console.WriteLine("Program complete. Press any key to exit...")
            Console.ReadKey()
        End Sub
        

        End Module

        Public Module HelperExtensions
        <System.Runtime.CompilerServices.Extension()> _
        Public Sub Dispose(ByVal this As Object)
        Console.WriteLine("Extension dispose")
        End Sub
        End Module

        Public Class Disposer(Of T)
        Public Sub New(ByVal data As T)
        _data = data
        End Sub

        Private \_data As T
        
        Public Sub Cleanup()
            If \_data IsNot Nothing Then \_data.Dispose()
        End Sub
        

        End Class

        Public Class DisposableTest
        Implements IDisposable

        Public Sub Dispose() Implements IDisposable.Dispose
            Console.WriteLine("Class dispose called.")
        End Sub
        

        End Class

        If you run that, the output will show that the extension dispose is being called for both Disposers even though the data object for one of them is IDisposable.

        P 1 Reply Last reply
        0
        • G Gideon Engelberth

          Actually, it would. The generic overloading rules I assume you are basing your position on only apply at source compile time. Since the actual type is not known at the time your generic collection (or whatever) is compiled, you would end up always calling the extension method. A simple example to demonstrate:

          Module Module1

          Sub Main()
              Dim di As New Disposer(Of Integer)(43)
              Dim dd As New Disposer(Of DisposableTest)(New DisposableTest)
          
              Console.WriteLine("Disposing Disposer(Of Integer)")
              di.Cleanup()
              Console.WriteLine("Disposing Disposer(Of DisposableTest)")
              dd.Cleanup()
          
              Dim dtemp As New DisposableTest()
              Console.WriteLine("Disposing DisposableTest")
              dtemp.Dispose()
          
              Console.WriteLine("Program complete. Press any key to exit...")
              Console.ReadKey()
          End Sub
          

          End Module

          Public Module HelperExtensions
          <System.Runtime.CompilerServices.Extension()> _
          Public Sub Dispose(ByVal this As Object)
          Console.WriteLine("Extension dispose")
          End Sub
          End Module

          Public Class Disposer(Of T)
          Public Sub New(ByVal data As T)
          _data = data
          End Sub

          Private \_data As T
          
          Public Sub Cleanup()
              If \_data IsNot Nothing Then \_data.Dispose()
          End Sub
          

          End Class

          Public Class DisposableTest
          Implements IDisposable

          Public Sub Dispose() Implements IDisposable.Dispose
              Console.WriteLine("Class dispose called.")
          End Sub
          

          End Class

          If you run that, the output will show that the extension dispose is being called for both Disposers even though the data object for one of them is IDisposable.

          P Offline
          P Offline
          PIEBALDconsult
          wrote on last edited by
          #5

          Hmmm... you're right, I didn't test it. I had originally written it with the test for IDisposable then removed it thinking it unnecessary. Ah well, it's not a serious piece of code anyway. On the other hand, I don't think it's supposed to work this way.

          S D 2 Replies Last reply
          0
          • P PIEBALDconsult

            Writing a generic collection and want to dispose of items that implement IDisposable, but don't want to bother checking each item or type for IDisposable? Why not associate a bogus Dispose method with every class that doesn't already have one? public static void Dispose ( this object Object ){} :cool: (Just be careful of non-IDisposable classes that have a Dispose method anyway. :suss: )

            S Offline
            S Offline
            supercat9
            wrote on last edited by
            #6

            While there are times that it would be nice to have Dispose work as a do-nothing for classes that do not implement iDisposable (e.g. I don't see any reason "using" shouldn't work even when it's superfluous), decisions of whether or not to dispose objects should almost always be made on the basis of something other than whether or not the object is of a disposable type. I can imagine considerable utility for a collection which includes a routine to add items and flag them as being both disposable [i]and owned by the collection[/i], so that when the collection is Dispose'd the items will be as well. For best reliability, the item should be passed as a reference parameter and zeroed when the item is added (if an exception is thrown while adding the item, the reference should be null if the item had been added to the list before the exception was thrown, and non-null if it had not). By the way, I use a global routine called Zap which accepts an iDisposable by reference; if the iDisposable is null, the routine simply exits. Otherwise it calls Dispose on the passed-in object and nulls out the passed-in object reference.

            P 1 Reply Last reply
            0
            • S supercat9

              While there are times that it would be nice to have Dispose work as a do-nothing for classes that do not implement iDisposable (e.g. I don't see any reason "using" shouldn't work even when it's superfluous), decisions of whether or not to dispose objects should almost always be made on the basis of something other than whether or not the object is of a disposable type. I can imagine considerable utility for a collection which includes a routine to add items and flag them as being both disposable [i]and owned by the collection[/i], so that when the collection is Dispose'd the items will be as well. For best reliability, the item should be passed as a reference parameter and zeroed when the item is added (if an exception is thrown while adding the item, the reference should be null if the item had been added to the list before the exception was thrown, and non-null if it had not). By the way, I use a global routine called Zap which accepts an iDisposable by reference; if the iDisposable is null, the routine simply exits. Otherwise it calls Dispose on the passed-in object and nulls out the passed-in object reference.

              P Offline
              P Offline
              PIEBALDconsult
              wrote on last edited by
              #7

              supercat9 wrote:

              I don't see any reason "using" shouldn't work even when it's superfluous

              Indeed. My feeling is that either object should implement IDisposable ( X| ) or the using statement shouldn't rely on the IDisposable interface. In fact I dislike language features that rely on the framework.

              L S 2 Replies Last reply
              0
              • P PIEBALDconsult

                supercat9 wrote:

                I don't see any reason "using" shouldn't work even when it's superfluous

                Indeed. My feeling is that either object should implement IDisposable ( X| ) or the using statement shouldn't rely on the IDisposable interface. In fact I dislike language features that rely on the framework.

                L Offline
                L Offline
                Luc Pattyn
                wrote on last edited by
                #8

                PIEBALDconsult wrote:

                I dislike language features that rely on the framework

                would that include "string literals" which get easily created, initialized and interned? :)

                Luc Pattyn


                I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages


                Local announcement (Antwerp region): Lange Wapper? 59.24% waren verstandig genoeg om NEEN te stemmen; bye bye viaduct.


                P 1 Reply Last reply
                0
                • P PIEBALDconsult

                  Hmmm... you're right, I didn't test it. I had originally written it with the test for IDisposable then removed it thinking it unnecessary. Ah well, it's not a serious piece of code anyway. On the other hand, I don't think it's supposed to work this way.

                  S Offline
                  S Offline
                  supercat9
                  wrote on last edited by
                  #9

                  PIEBALDconsult wrote:

                  On the other hand, I don't think it's supposed to work this way.

                  Extension methods are, from what I understand, an ugly kludge which serves mainly to make Intellisense more useful, at the expense of introducing all sorts of potential weird bugs. If I had my druthers, compilers would support extension classes rather than extension methods; from a run-time perspective, objects of an extension class would in reality be objects of the underlying class; from a compiler perspective, they would be interchangeable, but the extension classes would support extension methods and properties in addition to the methods and properties of the underlying class. Failing that, the Intellisense usefulness of extension classes would be achieved by making it so that typing "object.extensionMethod(" would be automatically rearranged to "extensionMethod(object," so as to make clear what was actually happening.

                  P S 2 Replies Last reply
                  0
                  • L Luc Pattyn

                    PIEBALDconsult wrote:

                    I dislike language features that rely on the framework

                    would that include "string literals" which get easily created, initialized and interned? :)

                    Luc Pattyn


                    I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages


                    Local announcement (Antwerp region): Lange Wapper? 59.24% waren verstandig genoeg om NEEN te stemmen; bye bye viaduct.


                    P Offline
                    P Offline
                    PIEBALDconsult
                    wrote on last edited by
                    #10

                    string is a C# keyword, it is required by the language. In the implementation of C# for .net the string type is backed by the System.String type. I (well maybe not me, but someone) could implement the C# language for some other platform (OpenVMS perhaps). Such an implementation may not require that string be backed by System.String, the language doesn't demand it. In .net, the using statement relies on the existence of an System.IDisposable interface. I feel that this is too tightly coupled. Were I to write my own implementation of C# I would not want to have to have an System.IDisposable interface, the language shouldn't demand it, it's not a keyword. Were I to write my own implementation of C# I would allow the using statement to operate on any type.

                    L 1 Reply Last reply
                    0
                    • S supercat9

                      PIEBALDconsult wrote:

                      On the other hand, I don't think it's supposed to work this way.

                      Extension methods are, from what I understand, an ugly kludge which serves mainly to make Intellisense more useful, at the expense of introducing all sorts of potential weird bugs. If I had my druthers, compilers would support extension classes rather than extension methods; from a run-time perspective, objects of an extension class would in reality be objects of the underlying class; from a compiler perspective, they would be interchangeable, but the extension classes would support extension methods and properties in addition to the methods and properties of the underlying class. Failing that, the Intellisense usefulness of extension classes would be achieved by making it so that typing "object.extensionMethod(" would be automatically rearranged to "extensionMethod(object," so as to make clear what was actually happening.

                      P Offline
                      P Offline
                      PIEBALDconsult
                      wrote on last edited by
                      #11

                      supercat9 wrote:

                      Extension methods are, from what I understand, an ugly kludge

                      Hear hear! And poorly implemented too. X|

                      1 Reply Last reply
                      0
                      • P PIEBALDconsult

                        supercat9 wrote:

                        I don't see any reason "using" shouldn't work even when it's superfluous

                        Indeed. My feeling is that either object should implement IDisposable ( X| ) or the using statement shouldn't rely on the IDisposable interface. In fact I dislike language features that rely on the framework.

                        S Offline
                        S Offline
                        supercat9
                        wrote on last edited by
                        #12

                        PIEBALDconsult wrote:

                        My feeling is that either object should implement IDisposable ( Dead )

                        Why the face? Because you think that would have been a good solution, or because you think it unfortunate that Object includes no such feature? Personally, I think Dispose would have been a better "standard" feature for an object than Finalize. Implementation of the standard dispose pattern requires that an object have a finalizer--even if it doesn't actually do anything--if derived classes may require non-null finalizers. Requiring that classes which implement finalizers must explicitly register them could eliminate that problem.

                        P G P 3 Replies Last reply
                        0
                        • S supercat9

                          PIEBALDconsult wrote:

                          My feeling is that either object should implement IDisposable ( Dead )

                          Why the face? Because you think that would have been a good solution, or because you think it unfortunate that Object includes no such feature? Personally, I think Dispose would have been a better "standard" feature for an object than Finalize. Implementation of the standard dispose pattern requires that an object have a finalizer--even if it doesn't actually do anything--if derived classes may require non-null finalizers. Requiring that classes which implement finalizers must explicitly register them could eliminate that problem.

                          P Offline
                          P Offline
                          PIEBALDconsult
                          wrote on last edited by
                          #13

                          Because I feel that not requiring the IDisposable interface is a cleaner solution.

                          1 Reply Last reply
                          0
                          • P PIEBALDconsult

                            string is a C# keyword, it is required by the language. In the implementation of C# for .net the string type is backed by the System.String type. I (well maybe not me, but someone) could implement the C# language for some other platform (OpenVMS perhaps). Such an implementation may not require that string be backed by System.String, the language doesn't demand it. In .net, the using statement relies on the existence of an System.IDisposable interface. I feel that this is too tightly coupled. Were I to write my own implementation of C# I would not want to have to have an System.IDisposable interface, the language shouldn't demand it, it's not a keyword. Were I to write my own implementation of C# I would allow the using statement to operate on any type.

                            L Offline
                            L Offline
                            Luc Pattyn
                            wrote on last edited by
                            #14

                            PIEBALDconsult wrote:

                            may not require that string be backed by System.String

                            I do want an easy way to initialize and to assign a new literal value to a System.String object. string literals, the thing understood by compilers, does exactly that; so for me a string literal must be a System.String I would not want to write string s=new string(new char[]{'H','e','l','l','o'}; !

                            PIEBALDconsult wrote:

                            I would allow the using statement to operate on any type

                            I'm not sure I like the idea; I can see some advantage, but then I don't want code to start looking like this:

                            using (int i=new int())
                            using (int j=new int())
                            for (i=0; i<10; i++) {
                            for (j=0; j<10; j++) {
                            ...
                            }
                            }

                            PIEBALDconsult wrote:

                            the using statement relies on the existence of an System.IDisposable interface

                            and what would you do about foreach? it needs an array, or an IEnumerable or an IEnumerable<T>. I got used to it and wouldn't like to loose it. And just ignoring the code block for objects that are not enumerable (without a warning/error) seems inappropriate. :)

                            Luc Pattyn


                            I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages


                            Local announcement (Antwerp region): Lange Wapper? 59.24% waren verstandig genoeg om NEEN te stemmen; bye bye viaduct.


                            modified on Monday, October 19, 2009 4:43 PM

                            P 1 Reply Last reply
                            0
                            • S supercat9

                              PIEBALDconsult wrote:

                              My feeling is that either object should implement IDisposable ( Dead )

                              Why the face? Because you think that would have been a good solution, or because you think it unfortunate that Object includes no such feature? Personally, I think Dispose would have been a better "standard" feature for an object than Finalize. Implementation of the standard dispose pattern requires that an object have a finalizer--even if it doesn't actually do anything--if derived classes may require non-null finalizers. Requiring that classes which implement finalizers must explicitly register them could eliminate that problem.

                              G Offline
                              G Offline
                              Gideon Engelberth
                              wrote on last edited by
                              #15

                              supercat9 wrote:

                              Implementation of the standard dispose pattern requires that an object have a finalizer

                              Not true!! You only need (and only should have) a finalizer if you explicitly use unmanaged resources yourself. If you simply use a managed class that has unmanaged resources (eg: StreamWriter), you do NOT need a finalizer. The StreamWriter will have its own finalizer that will take care of its resources. Since Finalize is already a virtual method, there is no need to override it just to let derived classes override it.

                              S 1 Reply Last reply
                              0
                              • L Luc Pattyn

                                PIEBALDconsult wrote:

                                may not require that string be backed by System.String

                                I do want an easy way to initialize and to assign a new literal value to a System.String object. string literals, the thing understood by compilers, does exactly that; so for me a string literal must be a System.String I would not want to write string s=new string(new char[]{'H','e','l','l','o'}; !

                                PIEBALDconsult wrote:

                                I would allow the using statement to operate on any type

                                I'm not sure I like the idea; I can see some advantage, but then I don't want code to start looking like this:

                                using (int i=new int())
                                using (int j=new int())
                                for (i=0; i<10; i++) {
                                for (j=0; j<10; j++) {
                                ...
                                }
                                }

                                PIEBALDconsult wrote:

                                the using statement relies on the existence of an System.IDisposable interface

                                and what would you do about foreach? it needs an array, or an IEnumerable or an IEnumerable<T>. I got used to it and wouldn't like to loose it. And just ignoring the code block for objects that are not enumerable (without a warning/error) seems inappropriate. :)

                                Luc Pattyn


                                I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages


                                Local announcement (Antwerp region): Lange Wapper? 59.24% waren verstandig genoeg om NEEN te stemmen; bye bye viaduct.


                                modified on Monday, October 19, 2009 4:43 PM

                                P Offline
                                P Offline
                                PIEBALDconsult
                                wrote on last edited by
                                #16

                                Luc Pattyn wrote:

                                I would not want to write string s=new string(new char[]{'H','e','l','l','o'}; !

                                I don't see why you'd have to.

                                Luc Pattyn wrote:

                                foreach

                                Oh, yeah, that was the other one, but it should work too.

                                S 1 Reply Last reply
                                0
                                • G Gideon Engelberth

                                  supercat9 wrote:

                                  Implementation of the standard dispose pattern requires that an object have a finalizer

                                  Not true!! You only need (and only should have) a finalizer if you explicitly use unmanaged resources yourself. If you simply use a managed class that has unmanaged resources (eg: StreamWriter), you do NOT need a finalizer. The StreamWriter will have its own finalizer that will take care of its resources. Since Finalize is already a virtual method, there is no need to override it just to let derived classes override it.

                                  S Offline
                                  S Offline
                                  supercat9
                                  wrote on last edited by
                                  #17

                                  I thought that the accepted dispose pattern was to have a finalizer which does nothing but "Dispose(False)" and then have any derived classes override Dispose(Boolean). Is that not how stuff is supposed to happen? Or is the expectation that stuff will happen like that, but each derived class is supposed to override the finalizer with (potentially yet another) finalizer that simply calls Dispose(False)? In any case, I would tend to think that having objects register for finalization would be better than having it occur automatically. Many objects that use unmanaged resources won't necessarily acquire them until some time after they're created. An object with a finalizer could unregister itself for garbage collection in its initializer and then re-register if it's going to allocate some unmanaged resources, but that would seem a little clunky.

                                  G 1 Reply Last reply
                                  0
                                  • S supercat9

                                    PIEBALDconsult wrote:

                                    On the other hand, I don't think it's supposed to work this way.

                                    Extension methods are, from what I understand, an ugly kludge which serves mainly to make Intellisense more useful, at the expense of introducing all sorts of potential weird bugs. If I had my druthers, compilers would support extension classes rather than extension methods; from a run-time perspective, objects of an extension class would in reality be objects of the underlying class; from a compiler perspective, they would be interchangeable, but the extension classes would support extension methods and properties in addition to the methods and properties of the underlying class. Failing that, the Intellisense usefulness of extension classes would be achieved by making it so that typing "object.extensionMethod(" would be automatically rearranged to "extensionMethod(object," so as to make clear what was actually happening.

                                    S Offline
                                    S Offline
                                    Super Lloyd
                                    wrote on last edited by
                                    #18

                                    supercat9 wrote:

                                    Extension methods are, from what I understand, an ugly kludge which serves mainly to make Intellisense more useful, at the expense of introducing all sorts of potential weird bugs.

                                    It's because, as you so well said, don't understand them! ;P

                                    A train station is where the train stops. A bus station is where the bus stops. On my desk, I have a work station.... _________________________________________________________ My programs never have bugs, they just develop random features.

                                    S 1 Reply Last reply
                                    0
                                    • P PIEBALDconsult

                                      Hmmm... you're right, I didn't test it. I had originally written it with the test for IDisposable then removed it thinking it unnecessary. Ah well, it's not a serious piece of code anyway. On the other hand, I don't think it's supposed to work this way.

                                      D Offline
                                      D Offline
                                      dojohansen
                                      wrote on last edited by
                                      #19

                                      PIEBALDconsult wrote:

                                      On the other hand, I don't think it's supposed to work this way.

                                      The compiler of course has no run-time type information when generating the code. Hence, it depends on the declared type of a reference to know where to look for members. Since the point of this code was to add a dummy Dispose to types that do not have Dispose, the only possible match is the extension methods. Personally, I find extension methods to be largely fluff. There is absolutely nothing an extension method can achieve that cannot be achieved with traditional utility methods. Calling class methods using instance syntax is also somewhat confusing, and generally such features tend to be seen as "cool" and misused accordingly. Much of the same can be said of initializers, though they are at least useful for anonymous types (which is a useful addition to the language). However, the one saving grace of extension methods have to do with a less technical aspect. It can be difficult to keep one's code base so well organized that it's always easy to find (and thus use) one's available utility methods. With extension methods it's possible to have a collection of them in one or any number of classes and discover the relevant ones via intellisense by remembering nothing more than to include a using directive. Some would also say it results in "more readable code", though I think that's rather mixed. string s = textBox1.Text.Reverse(); may be easier to read than string s = StrUtil.Reverse(s);, but since the latter actually shows what happens and the first one does not, it's not necessarily "more readable"!

                                      S 1 Reply Last reply
                                      0
                                      • S Super Lloyd

                                        supercat9 wrote:

                                        Extension methods are, from what I understand, an ugly kludge which serves mainly to make Intellisense more useful, at the expense of introducing all sorts of potential weird bugs.

                                        It's because, as you so well said, don't understand them! ;P

                                        A train station is where the train stops. A bus station is where the bus stops. On my desk, I have a work station.... _________________________________________________________ My programs never have bugs, they just develop random features.

                                        S Offline
                                        S Offline
                                        supercat9
                                        wrote on last edited by
                                        #20

                                        Super Lloyd wrote:

                                        It's because, as you so well said, don't understand them!

                                        Suppose I write "foo.bar()". What circumstances will determine whether this:

                                        1. Produces a build-time error
                                        2. Produces code which will throw "method not implemented" at run-time
                                        3. Execute a native method of foo's class
                                        4. Execute an extension method (if several exist, which one?)

                                        In the absence of extension methods, if an object is used in two contexts where it is declared identically. foo.bar() will perform the same action in both contexts. It may perform different actions on different objects, and the actions may depend upon how foo is declared, but the objects actual and declared types together serve to completely define the object's public fields, methods, and behaviors. What precisely determines what code will run when foo.bar() is executed on a system which uses extension methods?

                                        S 1 Reply Last reply
                                        0
                                        • S supercat9

                                          I thought that the accepted dispose pattern was to have a finalizer which does nothing but "Dispose(False)" and then have any derived classes override Dispose(Boolean). Is that not how stuff is supposed to happen? Or is the expectation that stuff will happen like that, but each derived class is supposed to override the finalizer with (potentially yet another) finalizer that simply calls Dispose(False)? In any case, I would tend to think that having objects register for finalization would be better than having it occur automatically. Many objects that use unmanaged resources won't necessarily acquire them until some time after they're created. An object with a finalizer could unregister itself for garbage collection in its initializer and then re-register if it's going to allocate some unmanaged resources, but that would seem a little clunky.

                                          G Offline
                                          G Offline
                                          Gideon Engelberth
                                          wrote on last edited by
                                          #21

                                          The pattern as I understand it is to have the finalizer call Dispose(False), BUT you only have a finalizer when you directly hold unmanaged resources (usually stored as an IntPtr). The VB IDE spits out some decent code to get you started with the pattern as I understand it. That code will then look something like this (this is typed by hand, YMMV):

                                          Private alreadyDisposed As Boolean
                                          Protected Overridable Sub Dispose(disposing As Boolean)
                                          'Do not release things more than once. The Dispose method should
                                          'be able to be called multiple times
                                          If Not alreadyDisposed Then
                                          If disposing
                                          'clean up managed disposables
                                          If mySerialPort IsNot Nothing Then mySerialPort.Dispose()
                                          End If

                                              'clean up unmanaged resources, such as IntPtrs
                                          
                                              alreadyDisposed = True
                                          End If
                                          

                                          End Sub

                                          Public Sub Dispose() Implements IDisposable.Dispose
                                          Dispose(True)
                                          'If you don't have a finalizer, this will do nothing
                                          GC.SuppressFinalize(Me)
                                          End Sub

                                          'if you need it (the IDE does not generate this
                                          'method because it is normally not needed):
                                          Protected Overrides Sub Finalize()
                                          'this method is only needed if you have unmanaged resources
                                          Try
                                          Dispose(False)
                                          Finally
                                          'don't forget to call the base
                                          MyBase.Finalize()
                                          End Try
                                          End Sub

                                          One thing I don't know is what will happen if you derive from a class with a finalizer and do not implement a finalizer on the derived class. My assumption is that the object will still be finalized, but it is just a guess. The safest thing to do would be to reimplement the Finalize method which will turn the base finalizers into do-nothing routines because dispose was already called. As far as the registering for finalization, I would recommend the approach to make the finalizable object as small as possible so that it is only created when the resource is acquired. This may mean creating another class to contain the resource and giving the bigger class that does not use the resource right away a field of the new type. The bigger class will no longer need to be finalizable and there will be no unnecessary finalizations or unregistration/registration required.

                                          S 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