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 8 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.
  • 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
    • G Gideon Engelberth

      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 Offline
      S Offline
      supercat9
      wrote on last edited by
      #22

      I just looked at the auto-generated code, and it seems that there is a #Region created with a parameterless Dispose() which calls Dispose(True) and SuppressFinalize, but does not actually contain a finalizer (though if a finalizer is created, it's supposed to call Dispose(False)). That seems like a good approach to doing things. Your comment about minimizing the actual Finalizable "footprint" is a good one. Among other things, if an object controls multiple unmanaged objects, splitting things up would allow separate finalizers for each. BTW, are there any sorts of well-designed objects which use finalizers but do not implement iDisposable? I still find it strange that all objects inherit Finalize, but not Dispose.

      S 1 Reply Last reply
      0
      • S supercat9

        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 Offline
        S Offline
        Super Lloyd
        wrote on last edited by
        #23

        I think it's relatively simple. The declared method of the declared type will be called if it exist. Otherwise it will throw a compile time error unless there is an extension method with such a name for such a declared type in the static classes of the declared using in the referenced DLLs. (I don't know what the "not implemented exception" does there, it will be thrown when whatever method throwing it is called) Further, if you use VS and thanks to intellisense, you'll know right away if: 1. the method exits 2. the method is on the declared type 3. the method is an extension method none of this should requires much though as: 1. when you use an object and call the method, and assuming you are not producing random code ;), you know very well what are the methods on the type that you are interested in! in other word mot only you don't have to think if you use VS, but also, extension method are not ambiguous at all! heck, me who use extension method a lot, the only problem I found them is that I have to write the "using namespace" explicitly myself, as VS won't do it!

        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.

        P 1 Reply Last reply
        0
        • S Super Lloyd

          I think it's relatively simple. The declared method of the declared type will be called if it exist. Otherwise it will throw a compile time error unless there is an extension method with such a name for such a declared type in the static classes of the declared using in the referenced DLLs. (I don't know what the "not implemented exception" does there, it will be thrown when whatever method throwing it is called) Further, if you use VS and thanks to intellisense, you'll know right away if: 1. the method exits 2. the method is on the declared type 3. the method is an extension method none of this should requires much though as: 1. when you use an object and call the method, and assuming you are not producing random code ;), you know very well what are the methods on the type that you are interested in! in other word mot only you don't have to think if you use VS, but also, extension method are not ambiguous at all! heck, me who use extension method a lot, the only problem I found them is that I have to write the "using namespace" explicitly myself, as VS won't do it!

          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.

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

          Super Lloyd wrote:

          The declared method of the declared type will be called if it exist.

          That's what I thought until I started this thread.

          S 1 Reply Last reply
          0
          • P PIEBALDconsult

            Super Lloyd wrote:

            The declared method of the declared type will be called if it exist.

            That's what I thought until I started this thread.

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

            I think you were thinking the method of the.... runtime type will be called. But there is no ambiguity and no runtime checking, it all happen at compile time! so if you wrote object o; o.foo() That would fail, because there is no foo() method on object. If it compiles that means that the foo() extension has been detected (at compile) and will be called. And nothing will change, i.e. if o is not only an object but a subclass which has a foo() method, this method won't be called by surprise contrary to the original extension, the extension will still be called as has been decided at compile time. With extension method there is no runtime snafu to fear, it all happen at compile time and compile time only!

            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
            • S Super Lloyd

              I think you were thinking the method of the.... runtime type will be called. But there is no ambiguity and no runtime checking, it all happen at compile time! so if you wrote object o; o.foo() That would fail, because there is no foo() method on object. If it compiles that means that the foo() extension has been detected (at compile) and will be called. And nothing will change, i.e. if o is not only an object but a subclass which has a foo() method, this method won't be called by surprise contrary to the original extension, the extension will still be called as has been decided at compile time. With extension method there is no runtime snafu to fear, it all happen at compile time and compile time only!

              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
              #26

              So are you saying that the extension method will get called if and only if the compiler was unaware of a normally-declared method when the code was built? What happens if between rebuilds a class in a library gets updated and a new property, method, or field gets added which shadows an extension method? My understanding is that the component-oriented architecture was designed to allow methods, properties, and fields to be added to classes without breaking applications that use them (such applications will never attempt to reference the new methods, properties, and fields, and will be unaware of their existence). In the absence of extension methods, if new methods are added to a library but all pre-existing methods, properties, etc. are unchanged, updating the library in an existing project will not affect the project application's behavior. If applications that use a class might have extension methods, how can one safely add classes, methods, or fields to it without potentially breaking applications of which one might be unaware?

              S M S 3 Replies Last reply
              0
              • S supercat9

                So are you saying that the extension method will get called if and only if the compiler was unaware of a normally-declared method when the code was built? What happens if between rebuilds a class in a library gets updated and a new property, method, or field gets added which shadows an extension method? My understanding is that the component-oriented architecture was designed to allow methods, properties, and fields to be added to classes without breaking applications that use them (such applications will never attempt to reference the new methods, properties, and fields, and will be unaware of their existence). In the absence of extension methods, if new methods are added to a library but all pre-existing methods, properties, etc. are unchanged, updating the library in an existing project will not affect the project application's behavior. If applications that use a class might have extension methods, how can one safely add classes, methods, or fields to it without potentially breaking applications of which one might be unaware?

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

                It's an interesting scenario that you just outlined, that can indeed happen. I won't elaborate too much on it (it's left as an exrcise to the reader ;P ), just say that in practice that hasn't happen to me yet. As I created extension method, so far, only for enums, interfaces and the following BCL classes: string, Stream (which haven't changed their signature much), so, in my case, I would say it's pretty safe. On a late note I would say the "problem" you outlined was on purpose, I think it's used in some of the LINQ libraries.

                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.

                P 1 Reply Last reply
                0
                • S Super Lloyd

                  It's an interesting scenario that you just outlined, that can indeed happen. I won't elaborate too much on it (it's left as an exrcise to the reader ;P ), just say that in practice that hasn't happen to me yet. As I created extension method, so far, only for enums, interfaces and the following BCL classes: string, Stream (which haven't changed their signature much), so, in my case, I would say it's pretty safe. On a late note I would say the "problem" you outlined was on purpose, I think it's used in some of the LINQ libraries.

                  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.

                  P Offline
                  P Offline
                  Paulo Zemek
                  wrote on last edited by
                  #28

                  I use extension methods a lot, and don't face the problems that "could" eventually happen. But, that's because using them a lot and using them in strange manners is different. For example, let's see the Stream class: Write(buffer, index, count); But, in general, I call: Write(buffer, 0, buffer.Length); So, I created an extension method that does this. If, in the future, there is a Write method with only one parameter, I really think it will still do the same I did, so I don't see a problem. One pair of things I really think should be done with extension methods is "Equals and GetHashCode". I really think these should only exist on objects that implement IEquatable (or IEquatable generic) interface. And, by default, an extension method could check if the object implement thems and, if not, return the ReferenceEquals or the "reference id" of the object. I think that actually it is horrible to know when an object implements equals and when it does not implements. But that's not the case here.

                  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.

                    P Offline
                    P Offline
                    Paulo Zemek
                    wrote on last edited by
                    #29

                    You don't need to implement the finalizer. The problem arises with the use of Dispose() calling Dispose(true) and the finalizer calling Dispose(false). You can always create your class with only Dispose() virtual. And, an inheritor that needs the destructor/finalize, makes the Dispose() as Dispose(true) and sealed, and creates the Dispose(bool disposing) and the finalizer. Very simple.

                    1 Reply Last reply
                    0
                    • S supercat9

                      So are you saying that the extension method will get called if and only if the compiler was unaware of a normally-declared method when the code was built? What happens if between rebuilds a class in a library gets updated and a new property, method, or field gets added which shadows an extension method? My understanding is that the component-oriented architecture was designed to allow methods, properties, and fields to be added to classes without breaking applications that use them (such applications will never attempt to reference the new methods, properties, and fields, and will be unaware of their existence). In the absence of extension methods, if new methods are added to a library but all pre-existing methods, properties, etc. are unchanged, updating the library in an existing project will not affect the project application's behavior. If applications that use a class might have extension methods, how can one safely add classes, methods, or fields to it without potentially breaking applications of which one might be unaware?

                      M Offline
                      M Offline
                      Mike Marynowski
                      wrote on last edited by
                      #30

                      supercat9 wrote:

                      So are you saying that the extension method will get called if and only if the compiler was unaware of a normally-declared method when the code was built?

                      Yes, that is correct. Extensions methods are just shorthand - they get converted to the static method call upon compilation, so updating the library with a method name that "conflicts" with the extension name will still call the extension method. That is, unless you recompile the code that called the extension method before, because it will now point to the instance method :)

                      1 Reply Last reply
                      0
                      • D dojohansen

                        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 Offline
                        S Offline
                        supercat9
                        wrote on last edited by
                        #31

                        I recognize that extension methods make Intellisense more useful, but a similar result could have been achieved by allowing methods to be tagged as auto-Intellisense, so that they would be listed in the Intellisense pop-up. Typing "textbox1.Text." might include a reverse function in the pop-up list, but selecting it would replace the period after "text" with a right-paren, and insert "StrUtil.Reverse(" before it (if the method took more parameters, it would use a comma rather than a right-paren. Actually, one could leverage Intellisense further by using a double-dot notation for extension methods (since double-dot is not otherwise legitimate, Intellisense would know that when a programmer typed "objectname.." he wanted a list of declared applicable methods. For that matter, that might not have been a bad syntax for extension methods. Conceptually, I wouldn't mind extension methods so much if they were distinct from real ones. Having code change meaning on a rebuild, though, seems like a disaster waiting to happen, unless one always performs full rebuilds whenever anything changes.

                        D 1 Reply 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: )

                          D Offline
                          D Offline
                          Daniel Flower
                          wrote on last edited by
                          #32

                          IEnumerable<object> objects = ...;
                          foreach (IDisposable disposable in objects.OfType<IDisposable>())
                          {
                          disposable.Dispose();
                          }

                          (OfType<T> is an extension method for IEnumerable<T> in the System.Linq namespace)

                          P 1 Reply Last reply
                          0
                          • D Daniel Flower

                            IEnumerable<object> objects = ...;
                            foreach (IDisposable disposable in objects.OfType<IDisposable>())
                            {
                            disposable.Dispose();
                            }

                            (OfType<T> is an extension method for IEnumerable<T> in the System.Linq namespace)

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

                            Because I don't like Extension Methods. :-D

                            1 Reply Last reply
                            0
                            • S supercat9

                              So are you saying that the extension method will get called if and only if the compiler was unaware of a normally-declared method when the code was built? What happens if between rebuilds a class in a library gets updated and a new property, method, or field gets added which shadows an extension method? My understanding is that the component-oriented architecture was designed to allow methods, properties, and fields to be added to classes without breaking applications that use them (such applications will never attempt to reference the new methods, properties, and fields, and will be unaware of their existence). In the absence of extension methods, if new methods are added to a library but all pre-existing methods, properties, etc. are unchanged, updating the library in an existing project will not affect the project application's behavior. If applications that use a class might have extension methods, how can one safely add classes, methods, or fields to it without potentially breaking applications of which one might be unaware?

                              S Offline
                              S Offline
                              S Senthil Kumar
                              wrote on last edited by
                              #34

                              supercat9 wrote:

                              ). In the absence of extension methods, if new methods are added to a library but all pre-existing methods, properties, etc. are unchanged, updating the library in an existing project will not affect the project application's behavior. If applications that use a class might have extension methods, how can one safely add classes, methods, or fields to it without potentially breaking applications of which one might be unaware?

                              Actually, that's not true, unless you don't consider overloading a method to be a new method. Overload resolution could find a new method to be a better match.

                              V1

                              class C
                              {
                              void Foo(object o) {}
                              }

                              V2

                              class C
                              {
                              void Foo(object o) {}
                              void Foo(int x){}
                              }

                              new C().Foo(1) will now resolve to the int overload. If Foo was virtual, and you'd derived from C and overridden Foo(object), your code wouldn't get called either.

                              Regards Senthil _____________________________ My Home Page |My Blog | My Articles | My Flickr | WinMacro

                              1 Reply Last reply
                              0
                              • P PIEBALDconsult

                                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 Offline
                                S Offline
                                S Senthil Kumar
                                wrote on last edited by
                                #35

                                How about lock then?

                                Regards Senthil _____________________________ My Home Page |My Blog | My Articles | My Flickr | WinMacro

                                P 1 Reply Last reply
                                0
                                • S supercat9

                                  I just looked at the auto-generated code, and it seems that there is a #Region created with a parameterless Dispose() which calls Dispose(True) and SuppressFinalize, but does not actually contain a finalizer (though if a finalizer is created, it's supposed to call Dispose(False)). That seems like a good approach to doing things. Your comment about minimizing the actual Finalizable "footprint" is a good one. Among other things, if an object controls multiple unmanaged objects, splitting things up would allow separate finalizers for each. BTW, are there any sorts of well-designed objects which use finalizers but do not implement iDisposable? I still find it strange that all objects inherit Finalize, but not Dispose.

                                  S Offline
                                  S Offline
                                  S Senthil Kumar
                                  wrote on last edited by
                                  #36

                                  supercat9 wrote:

                                  I still find it strange that all objects inherit Finalize, but not Dispose.

                                  I think it's because the CLR calls Finalize, but developers are supposed to call Dispose. The CLR doesn't consider an object to be finalizable if it doesn't override the implemenation derived from Object. If all types have Dispose, it'd be hard for developers to figure out the types for which they'll have to call Dispose.

                                  supercat9 wrote:

                                  BTW, are there any sorts of well-designed objects which use finalizers but do not implement iDisposable?

                                  That'd be a bug, wouldn't it? The object holds resources that need to be released, but it doesn't allow the user to release them early.

                                  Regards Senthil _____________________________ My Home Page |My Blog | My Articles | My Flickr | WinMacro

                                  1 Reply Last reply
                                  0
                                  • S S Senthil Kumar

                                    How about lock then?

                                    Regards Senthil _____________________________ My Home Page |My Blog | My Articles | My Flickr | WinMacro

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

                                    I don't think that relies specifically on anything in .net; it could be implemented differently.

                                    S 1 Reply Last reply
                                    0
                                    • P PIEBALDconsult

                                      I don't think that relies specifically on anything in .net; it could be implemented differently.

                                      S Offline
                                      S Offline
                                      S Senthil Kumar
                                      wrote on last edited by
                                      #38

                                      Well, it calls Monitor.Enter and Monitor.Exit, and they are specific types in the .NET BCL.

                                      Regards Senthil _____________________________ My Home Page |My Blog | My Articles | My Flickr | WinMacro

                                      P 1 Reply Last reply
                                      0
                                      • S S Senthil Kumar

                                        Well, it calls Monitor.Enter and Monitor.Exit, and they are specific types in the .NET BCL.

                                        Regards Senthil _____________________________ My Home Page |My Blog | My Articles | My Flickr | WinMacro

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

                                        That's just implementation; a different implementation could do something different.

                                        S 1 Reply Last reply
                                        0
                                        • P PIEBALDconsult

                                          That's just implementation; a different implementation could do something different.

                                          S Offline
                                          S Offline
                                          S Senthil Kumar
                                          wrote on last edited by
                                          #40

                                          Can't you make the same argument for using as well? Your implementation could ignore types that don't implement IDisposable, for example.

                                          Regards Senthil _____________________________ My Home Page |My Blog | My Articles | My Flickr | WinMacro

                                          P 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