GC! Why not ref count?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Ron James

    GC! Why not ref count?

    C++ is a great language. You can instantiate an object on
    the stack, grab whatever resources you need, and free them
    in the destructor. Object destructors are called in the
    correct order (the reverse order), and are guaranteed to
    be called when the object goes out of scope.

    Unfortunately this is not so in C# (or Java) since you
    cannot tell when the Garbage Collector will run. In C#
    you can call Dispose (assuming it's implemented), but you
    you still might have several references to a invalid
    object floating around. Alternatively you can take
    advantage of the using statement IF the class implements
    IDispose, however this can become unwieldy if you need
    several nested using blocks.

    So why did the developers of C# (and Java) not reference
    count objects? Surely it would have been a simple matter
    to implement reference counting, and guarantee calling the
    destructor when the last reference to an object was set to
    null. The GC could still run periodically to clean up and
    re-organize memory, but at least the resource cleanup
    problem would have been solved.

    What am I missing?

    Thanks.
  • Tom Shelton

    #2
    Re: GC! Why not ref count?


    "Ron James" <Ron.James@noap sm.rojacs.com> wrote in message
    news:09eb01c34b d5$13a518d0$a00 1280a@phx.gbl.. .[color=blue]
    > C++ is a great language. You can instantiate an object on
    > the stack, grab whatever resources you need, and free them
    > in the destructor. Object destructors are called in the
    > correct order (the reverse order), and are guaranteed to
    > be called when the object goes out of scope.[/color]

    That is only true of stack allocated objects. If you have heap allocated
    objects then you are responsible for calling delete when done with the
    object. This causes many problems... Memory leaks (no delete), calling
    delete on invalid pointer (crash!), calling delete to an object that is
    still needed (crash! or corruption). GC is popular because it frees the
    programmer from the need to explicitly manage memory allocation.
    [color=blue]
    > Unfortunately this is not so in C# (or Java) since you
    > cannot tell when the Garbage Collector will run. In C#
    > you can call Dispose (assuming it's implemented), but you
    > you still might have several references to a invalid
    > object floating around. Alternatively you can take
    > advantage of the using statement IF the class implements
    > IDispose, however this can become unwieldy if you need
    > several nested using blocks.[/color]

    You are not understanding the Dispose pattern. Dispose is only implemented
    for classes that hold references to unmanaged resources - such as file
    handles, window handles, database connections, socket handles, etc.) These
    are limmited OS resources, that need to be returned as soon as possible. In
    other words, you don't want to wait around for your finalize method to be
    called for those resources to be released. Not only that, overriding
    finalize has negative consequences for GC performance - because it requires
    to GC's to completely destroy the object. So do get around that, MS has
    provided a pattern based approach for dealing with these types of resources
    via the IDisposable interface. Generally all necessary clean up is called
    from both the finalize method as well as the Dispose method, with the added
    step that System.GC.Suppr essFinalize will be called in the Dispose method.
    This lets you insure that unmanaged resources are cleaned up eventually -
    even if a developer forgets to call Dispose, but rewards those that do
    remember by removing the performance hit at GC time.
    [color=blue]
    > So why did the developers of C# (and Java) not reference
    > count objects? Surely it would have been a simple matter
    > to implement reference counting, and guarantee calling the
    > destructor when the last reference to an object was set to
    > null. The GC could still run periodically to clean up and
    > re-organize memory, but at least the resource cleanup
    > problem would have been solved.[/color]

    Mostly because ref counting has several side affects.
    1) Performance - generally reference counting schemes do not perform as well
    as GC schemes as implemented in Java and .NET for the simple fact that they
    have to be thread safe, which mean syncronization must be in place.

    2) Referecne counting is easy to screw up. Often they are implmented using
    methods that increment or decrement the Ref count and it is up to the
    developer or the runtime to make sure these are called in a balanced manner.

    3) Ref counting doesn't deal with object cycles well (aka circular
    references). This is one of the major source of memory leaks in VB.CLASSIC.

    The fact is that the style of GC used by C#/Java is much more effiecient and
    less prone to error then reference counting...

    Tom Shelton


    Comment

    • Mattias Sjögren

      #3
      Re: GC! Why not ref count?

      Ron,

      This was debated *a lot* in the early days of .NET. I suggest you read
      this piece to get an idea of how the designers were thinking





      Mattias

      --
      Mattias Sjögren [MVP] mattias @ mvps.org

      Please reply only to the newsgroup.

      Comment

      • Mark Mullin

        #4
        Re: GC! Why not ref count?

        Check out some of the other OO languages which do handle large numbers
        of objects and deal with memory management. You'll see they all
        abandoned reference counting (mark and sweep) for two reasons

        1 - It's very expensive. You have to visit every node every pass. At
        least 2 times (mark and sweep pass) and once again if you're actually
        using it. Slooooooowwwwww wwwwwwwww.

        2 - It doesn't exploit the situation. Most objects are either created
        and blown away before they've drawn two breaths, or they stay around
        like my old socks. Smalltalk and CLOS both headed for generation
        scavenging in the early 90's, but I expect the fields become even more
        abstruse at this point.

        Comment

        • Andreas Huber

          #5
          Re: GC! Why not ref count?

          "Tom Shelton" <tshelt@yahoo.c om> wrote in message news:<#dGIZf9SD HA.1576@TK2MSFT NGP12.phx.gbl>. ..[color=blue]
          > "Ron James" <Ron.James@noap sm.rojacs.com> wrote in message
          > news:09eb01c34b d5$13a518d0$a00 1280a@phx.gbl.. .[/color]
          [snip][color=blue][color=green]
          > > Unfortunately this is not so in C# (or Java) since you
          > > cannot tell when the Garbage Collector will run. In C#
          > > you can call Dispose (assuming it's implemented), but you
          > > you still might have several references to a invalid
          > > object floating around. Alternatively you can take
          > > advantage of the using statement IF the class implements
          > > IDispose, however this can become unwieldy if you need
          > > several nested using blocks.[/color]
          >
          > You are not understanding the Dispose pattern. Dispose is only implemented
          > for classes that hold references to unmanaged resources - such as file
          > handles, window handles, database connections, socket handles, etc.)[/color]

          Ahem, you don't seem to understand it fully either or I have
          misunderstood it completely ;-). Whether a class implements
          IDisposable or not has nothing to do with the class having *unmanaged*
          resources. When a class implements IDisposable then it provides the
          outside world with a means to deterministical ly clean up resources -
          nothing more, nothing less. Some of these resources *might* be
          unmanaged of course, but only might. For example, have a look at
          System.IO.Binar yWriter. This class implements IDisposable but does
          itself not have unmanaged resources. Among other (managed) data
          members it owns a System.IO.Strea m object and a buffer. The Dispose()
          method is only there to flush that buffer and then close the
          underlying stream. If you fail to call Dispose() before letting the
          BinaryWriter object go out of scope you are guaranteed to lose some
          data, because BinaryWriter does not have a finalizer. This is
          intentional as you cannot access other managed objects (here: the
          stream) in a finalizer. Why? Because the order of finalization of no
          longer reachable objects is not defined. You might get lucky sometimes
          but it's definitely not guaranteed to work.

          Except for a few *very* esotheric cases, finalizers are only good to
          clean up _unmanaged_ resources. E.g. if you have a look at
          mscorlib.dll with ILDASM, you'll find that classes which have
          unmanaged resources invariably also implement a finalizer. To avoid
          code duplication, some of them combine finalization with disposal in a
          pattern (the one with the virtual Dispose( bool dispose ) function).
          Dispose() can be used to clean up managed *and* unmanaged resources
          while Finalize() only releases the unmanaged resources.
          [color=blue]
          > These
          > are limmited OS resources, that need to be returned as soon as possible. In
          > other words, you don't want to wait around for your finalize method to be
          > called for those resources to be released.[/color]

          True, but only part of the story, see above.
          [color=blue]
          > via the IDisposable interface. Generally all necessary clean up is called
          > from both the finalize method as well as the Dispose method, with the added[/color]

          Finalize() only cleans up unmanaged resources, see above.

          [snip][color=blue]
          > 2) Referecne counting is easy to screw up. Often they are implmented using
          > methods that increment or decrement the Ref count and it is up to the
          > developer or the runtime to make sure these are called in a balanced manner.[/color]

          Yep, but it's also quite easy to get right. E.g. see



          Regards,

          Andreas

          Comment

          • ncaHammer

            #6
            Re: GC! Why not ref count?

            "Andreas Huber" <ah2003@gmx.net > wrote in message
            news:3ede0f29.0 307170435.33de3 3f1@posting.goo gle.com...[color=blue]
            > Finalize() only cleans up unmanaged resources, see above.[/color]

            QUIZ : Why then Regex has a Finalizer ?
            there is a ref counting mechanism under it
            this approach is either extremely sophisticated (and i cannot understand
            it) or extremely stupid


            Comment

            • Andreas Huber

              #7
              Re: GC! Why not ref count?

              ncaHammer wrote:[color=blue]
              > "Andreas Huber" <ah2003@gmx.net > wrote in message
              > news:3ede0f29.0 307170435.33de3 3f1@posting.goo gle.com...[color=green]
              >> Finalize() only cleans up unmanaged resources, see above.[/color]
              >
              > QUIZ : Why then Regex has a Finalizer ?
              > there is a ref counting mechanism under it
              > this approach is either extremely sophisticated (and i cannot
              > understand it) or extremely stupid[/color]

              I've just had a look at the the class with ILDASM. This seems to be one of
              the esotheric uses of finalizers I was talking about in the lines above the
              one you quoted. Regex has a static HashTable field called "livecode". I'm
              far from being proficient with MSIL so I don't really understand the code,
              but it seems that all constructors put something in it while the destructor
              (Finalizer) removes something from it. This is safe because the static data
              member is supposed (guaranteed?) to exist at least as long as Regex objects.

              Definitely, there are other uses for finalizers than just cleaning up
              unmanaged resources. However, as I explained, you're quite limited in what
              you can safely do with them. The other non-cleanup use I know uses
              finalizers to implement an object pool and - no wonder - also only accesses
              static data members in the finalizer.

              I bet you won't find many such finalizers in the .NET framework.

              Regards,

              Andreas

              Comment

              • Tom Shelton

                #8
                Re: GC! Why not ref count?


                "Andreas Huber" <ah2003@gmx.net > wrote in message
                news:3ede0f29.0 307170435.33de3 3f1@posting.goo gle.com...[color=blue]
                > "Tom Shelton" <tshelt@yahoo.c om> wrote in message[/color]
                news:<#dGIZf9SD HA.1576@TK2MSFT NGP12.phx.gbl>. ..[color=blue][color=green]
                > > "Ron James" <Ron.James@noap sm.rojacs.com> wrote in message
                > > news:09eb01c34b d5$13a518d0$a00 1280a@phx.gbl.. .[/color]
                > [snip][color=green][color=darkred]
                > > > Unfortunately this is not so in C# (or Java) since you
                > > > cannot tell when the Garbage Collector will run. In C#
                > > > you can call Dispose (assuming it's implemented), but you
                > > > you still might have several references to a invalid
                > > > object floating around. Alternatively you can take
                > > > advantage of the using statement IF the class implements
                > > > IDispose, however this can become unwieldy if you need
                > > > several nested using blocks.[/color]
                > >
                > > You are not understanding the Dispose pattern. Dispose is only[/color][/color]
                implemented[color=blue][color=green]
                > > for classes that hold references to unmanaged resources - such as file
                > > handles, window handles, database connections, socket handles, etc.)[/color]
                >
                > Ahem, you don't seem to understand it fully either or I have
                > misunderstood it completely ;-). Whether a class implements
                > IDisposable or not has nothing to do with the class having *unmanaged*
                > resources. When a class implements IDisposable then it provides the
                > outside world with a means to deterministical ly clean up resources -
                > nothing more, nothing less. Some of these resources *might* be
                > unmanaged of course, but only might. For example, have a look at
                > System.IO.Binar yWriter. This class implements IDisposable but does
                > itself not have unmanaged resources. Among other (managed) data
                > members it owns a System.IO.Strea m object and a buffer. The Dispose()
                > method is only there to flush that buffer and then close the
                > underlying stream. If you fail to call Dispose() before letting the
                > BinaryWriter object go out of scope you are guaranteed to lose some
                > data, because BinaryWriter does not have a finalizer. This is
                > intentional as you cannot access other managed objects (here: the
                > stream) in a finalizer. Why? Because the order of finalization of no
                > longer reachable objects is not defined. You might get lucky sometimes
                > but it's definitely not guaranteed to work.[/color]

                Hello! BinaryWritter takes a stream as one of the arguments to both it's
                public constructors... That stream is almost certainly going to have an
                underlying OS resource - FileStream or NetworkStream for example. In other
                words, though BinaryWriter doesn't itself contain a unmanaged resource, it
                contains a class that does - hence the need for dispose.
                [color=blue]
                > Except for a few *very* esotheric cases, finalizers are only good to
                > clean up _unmanaged_ resources. E.g. if you have a look at
                > mscorlib.dll with ILDASM, you'll find that classes which have
                > unmanaged resources invariably also implement a finalizer. To avoid
                > code duplication, some of them combine finalization with disposal in a
                > pattern (the one with the virtual Dispose( bool dispose ) function).
                > Dispose() can be used to clean up managed *and* unmanaged resources
                > while Finalize() only releases the unmanaged resources.[/color]

                What managed resources will you clean up with dispose? Setting internal
                references to null isn't going to change anything... The only reason your
                example above implements dispose is that is a generic wrapper for a stream.
                A stream will almost certainly have a unmanaged resource at the root.
                [color=blue][color=green]
                > > These
                > > are limmited OS resources, that need to be returned as soon as possible.[/color][/color]
                In[color=blue][color=green]
                > > other words, you don't want to wait around for your finalize method to[/color][/color]
                be[color=blue][color=green]
                > > called for those resources to be released.[/color]
                >
                > True, but only part of the story, see above.[/color]

                Except that your story is wrong...
                [color=blue][color=green]
                > > via the IDisposable interface. Generally all necessary clean up is[/color][/color]
                called[color=blue][color=green]
                > > from both the finalize method as well as the Dispose method, with the[/color][/color]
                added[color=blue]
                >
                > Finalize() only cleans up unmanaged resources, see above.[/color]

                Yes, that is what I said, except you have the part about Dispose wrong.
                There is no reason to implement IDisposable if there are no unmanaged
                resources to clean up. Think about it...
                [color=blue]
                > [snip][color=green]
                > > 2) Referecne counting is easy to screw up. Often they are implmented[/color][/color]
                using[color=blue][color=green]
                > > methods that increment or decrement the Ref count and it is up to the
                > > developer or the runtime to make sure these are called in a balanced[/color][/color]
                manner.[color=blue]
                >
                > Yep, but it's also quite easy to get right. E.g. see
                >
                > http://www.boost.org/libs/smart_ptr/shared_ptr.htm[/color]

                Yes, I am aware of smart pointers...

                Tom Shelton


                Comment

                • Tom Shelton

                  #9
                  Re: GC! Why not ref count?


                  "Andreas Huber" <ah2003@gmx.net > wrote in message
                  news:3f16f57a$1 @news.swissonli ne.ch...[color=blue]
                  > ncaHammer wrote:[color=green]
                  > > "Andreas Huber" <ah2003@gmx.net > wrote in message
                  > > news:3ede0f29.0 307170435.33de3 3f1@posting.goo gle.com...[color=darkred]
                  > >> Finalize() only cleans up unmanaged resources, see above.[/color]
                  > >
                  > > QUIZ : Why then Regex has a Finalizer ?
                  > > there is a ref counting mechanism under it
                  > > this approach is either extremely sophisticated (and i cannot
                  > > understand it) or extremely stupid[/color]
                  >
                  > I've just had a look at the the class with ILDASM. This seems to be one of
                  > the esotheric uses of finalizers I was talking about in the lines above[/color]
                  the[color=blue]
                  > one you quoted. Regex has a static HashTable field called "livecode". I'm
                  > far from being proficient with MSIL so I don't really understand the code,
                  > but it seems that all constructors put something in it while the[/color]
                  destructor[color=blue]
                  > (Finalizer) removes something from it. This is safe because the static[/color]
                  data[color=blue]
                  > member is supposed (guaranteed?) to exist at least as long as Regex[/color]
                  objects.[color=blue]
                  >
                  > Definitely, there are other uses for finalizers than just cleaning up
                  > unmanaged resources. However, as I explained, you're quite limited in what
                  > you can safely do with them. The other non-cleanup use I know uses
                  > finalizers to implement an object pool and - no wonder - also only[/color]
                  accesses[color=blue]
                  > static data members in the finalizer.
                  >
                  > I bet you won't find many such finalizers in the .NET framework.
                  >
                  > Regards,
                  >
                  > Andreas[/color]

                  Having not looked at the IDL for this, my guess form this is that it is
                  stashing the compiled regular expressions, and then removing them when they
                  are no longer needed. This I guess a form of cleanup, you have to remove a
                  reference to the compiled code or it would stay there for ever in the static
                  object. It is very similar to your reference to object pooling above.

                  Tom Shelton


                  Comment

                  • ncaHammer

                    #10
                    Re: GC! Why not ref count?

                    "Tom Shelton" <tshelt@yahoo.c om> wrote in message
                    news:unKrgJKTDH A.2128@TK2MSFTN GP12.phx.gbl...[color=blue]
                    > Yes, that is what I said, except you have the part about Dispose wrong.
                    > There is no reason to implement IDisposable if there are no unmanaged
                    > resources to clean up. Think about it...[/color]

                    All components implement IDisposable and most of them don't hold any
                    unmanaged resources.
                    At design time (or at runtime) Disposing a component should remove any
                    references that any component (under the ISite) holds for it. This action
                    should restore the ISite component graph to the state it had before adding
                    this component.

                    for example :

                    ToolbarButton while not holding any unmanaged resource, it does implement
                    IDisposable. Disposing a toolbarbutton it removes it from the button
                    collection of the toolbar.

                    I don't know if i make my point clear. (my English are bad)
                    In a nutshell. Dispose is also used to maintain an object graph consistent.
                    You can interpret it as "on-delete trigger" in SQL terms


                    Comment

                    • Tom Shelton

                      #11
                      Re: GC! Why not ref count?


                      "ncaHammer" <ncahammer@nos. pamhot.mail.com > wrote in message
                      news:OGP5FdKTDH A.1664@TK2MSFTN GP11.phx.gbl...[color=blue]
                      > "Tom Shelton" <tshelt@yahoo.c om> wrote in message
                      > news:unKrgJKTDH A.2128@TK2MSFTN GP12.phx.gbl...[color=green]
                      > > Yes, that is what I said, except you have the part about Dispose wrong.
                      > > There is no reason to implement IDisposable if there are no unmanaged
                      > > resources to clean up. Think about it...[/color]
                      >
                      > All components implement IDisposable and most of them don't hold any
                      > unmanaged resources.
                      > At design time (or at runtime) Disposing a component should remove any
                      > references that any component (under the ISite) holds for it. This action
                      > should restore the ISite component graph to the state it had before adding
                      > this component.
                      >
                      > for example :
                      >
                      > ToolbarButton while not holding any unmanaged resource, it does implement
                      > IDisposable. Disposing a toolbarbutton it removes it from the button
                      > collection of the toolbar.[/color]

                      Ok, not something I had thought about - still I'm looking throught IDL :)
                      This usage seems about as strange as the use of finalize for object pooling.
                      I can see though why a component would have a dispose method - they just
                      might have unmanaged resources. What about database components etc...

                      Tom Shelton


                      Comment

                      • Tom Shelton

                        #12
                        Re: GC! Why not ref count?


                        "Tom Shelton" <tshelt@yahoo.c om> wrote in message
                        news:%23uDnd0KT DHA.1916@TK2MSF TNGP12.phx.gbl. ..[color=blue]
                        >
                        > "ncaHammer" <ncahammer@nos. pamhot.mail.com > wrote in message
                        > news:OGP5FdKTDH A.1664@TK2MSFTN GP11.phx.gbl...[color=green]
                        > > "Tom Shelton" <tshelt@yahoo.c om> wrote in message
                        > > news:unKrgJKTDH A.2128@TK2MSFTN GP12.phx.gbl...[color=darkred]
                        > > > Yes, that is what I said, except you have the part about Dispose[/color][/color][/color]
                        wrong.[color=blue][color=green][color=darkred]
                        > > > There is no reason to implement IDisposable if there are no unmanaged
                        > > > resources to clean up. Think about it...[/color]
                        > >
                        > > All components implement IDisposable and most of them don't hold any
                        > > unmanaged resources.
                        > > At design time (or at runtime) Disposing a component should remove any
                        > > references that any component (under the ISite) holds for it. This[/color][/color]
                        action[color=blue][color=green]
                        > > should restore the ISite component graph to the state it had before[/color][/color]
                        adding[color=blue][color=green]
                        > > this component.
                        > >
                        > > for example :
                        > >
                        > > ToolbarButton while not holding any unmanaged resource, it does[/color][/color]
                        implement[color=blue][color=green]
                        > > IDisposable. Disposing a toolbarbutton it removes it from the button
                        > > collection of the toolbar.[/color]
                        >
                        > Ok, not something I had thought about - still I'm looking throught IDL :)
                        > This usage seems about as strange as the use of finalize for object[/color]
                        pooling.[color=blue]
                        > I can see though why a component would have a dispose method - they just
                        > might have unmanaged resources. What about database components etc...
                        >
                        > Tom Shelton[/color]

                        Bye the way, I wouldn't say most components do not hold unmanaged
                        resources... Every winforms control is a component, since every control
                        inherits from component. I in fact would say that most components, do in
                        fact hold unmanaged resources (Controls, Timers, Connections, Messaging,
                        etc)

                        Tom Shelton


                        Comment

                        • Andreas Huber

                          #13
                          Re: GC! Why not ref count?

                          Tom Shelton wrote:
                          [snip][color=blue][color=green]
                          >> Ahem, you don't seem to understand it fully either or I have
                          >> misunderstood it completely ;-). Whether a class implements
                          >> IDisposable or not has nothing to do with the class having
                          >> *unmanaged* resources. When a class implements IDisposable then it
                          >> provides the outside world with a means to deterministical ly clean
                          >> up resources - nothing more, nothing less. Some of these resources
                          >> *might* be
                          >> unmanaged of course, but only might. For example, have a look at
                          >> System.IO.Binar yWriter. This class implements IDisposable but does
                          >> itself not have unmanaged resources. Among other (managed) data
                          >> members it owns a System.IO.Strea m object and a buffer. The Dispose()
                          >> method is only there to flush that buffer and then close the
                          >> underlying stream. If you fail to call Dispose() before letting the
                          >> BinaryWriter object go out of scope you are guaranteed to lose some
                          >> data, because BinaryWriter does not have a finalizer. This is
                          >> intentional as you cannot access other managed objects (here: the
                          >> stream) in a finalizer. Why? Because the order of finalization of no
                          >> longer reachable objects is not defined. You might get lucky
                          >> sometimes but it's definitely not guaranteed to work.[/color]
                          >
                          > Hello! BinaryWritter takes a stream as one of the arguments to both
                          > it's public constructors... That stream is almost certainly going to
                          > have an underlying OS resource - FileStream or NetworkStream for[/color]

                          Counter example: A MemoryStream object does not hold unmanaged OS resources.
                          [color=blue]
                          > example. In other words, though BinaryWriter doesn't itself contain
                          > a unmanaged resource, it contains a class that does - hence the need
                          > for dispose.[/color]

                          Nope. You need to call Dispose() even if you pass a MemoryStream object to
                          the BinaryWriter constructor or you are almost guaranteed to lose data,
                          although there aren't any unmanaged resources anywhere.
                          [color=blue]
                          >[color=green]
                          >> Except for a few *very* esotheric cases, finalizers are only good to
                          >> clean up _unmanaged_ resources. E.g. if you have a look at
                          >> mscorlib.dll with ILDASM, you'll find that classes which have
                          >> unmanaged resources invariably also implement a finalizer. To avoid
                          >> code duplication, some of them combine finalization with disposal in
                          >> a pattern (the one with the virtual Dispose( bool dispose )
                          >> function). Dispose() can be used to clean up managed *and* unmanaged
                          >> resources
                          >> while Finalize() only releases the unmanaged resources.[/color]
                          >
                          > What managed resources will you clean up with dispose?[/color]

                          As I tried to explain in my previous post, the problem is that BinaryWriter
                          itself holds a buffer. If you want the contents of that buffer to be flushed
                          into the stream, you *must* call Dispose(). ~BinaryWriter() (if it existed)
                          won't do that for you because the underlying stream might already be dead.
                          Whether or not the stream holds any unmanaged resources is simply
                          irrelevant.
                          If you fail to call Dispose() on the BinaryWriter object you will lose data,
                          even if the stream does not hold unmanaged resources.

                          [snip][color=blue]
                          > Yes, that is what I said, except you have the part about Dispose
                          > wrong. There is no reason to implement IDisposable if there are no
                          > unmanaged resources to clean up. Think about it...[/color]

                          You are right in as much as that the managed resources will all be released
                          correctly. However, you are wrong in terms of correctness because the
                          released resources might hold valuable data, which will simply be thrown
                          away if you fail to call Dispose() before letting the object go out of
                          scope.

                          Regards,

                          Andreas

                          Comment

                          • Andreas Huber

                            #14
                            Re: GC! Why not ref count?

                            Andreas Huber wrote:
                            [snip][color=blue]
                            > Nope. You need to call Dispose() even if you pass a MemoryStream
                            > object to the BinaryWriter constructor or you are almost guaranteed
                            > to lose data, although there aren't any unmanaged resources anywhere.[/color]
                            [snip]

                            Forget about BinaryWriter, it does not have an internal buffer. Instead,
                            have a look at StreamWriter.

                            Regards,

                            Andreas

                            Comment

                            • Lucean Morningside

                              #15
                              Re: GC! Why not ref count?

                              Hi Ron, gentlmen.

                              [color=blue]
                              > C++ is a great language.[/color]
                              Agreed
                              [color=blue]
                              > the stack, grab whatever resources you need, and free them
                              > in the destructor. Object destructors are called in the
                              > correct order (the reverse order), and are guaranteed to
                              > be called when the object goes out of scope.[/color]
                              As far as I can tell, you, as I had once, are missing the good old
                              "Resource acquisition is initialization (RAII)" idiom. Others have already
                              answered the technical reasons for choosing garbage collection instead of
                              reference counting, so I'll just keep my two cents on that subject to myself.
                              However, may I suggest that you take a look at the following article, which
                              does attempt to simulate the RAII idiom in C#:


                              Hope you'd find it useful.

                              Sincerely,
                              LM.

                              P.S. My apologies to you and others how are viewing this post if I have broken
                              proper etiquette, since this is my first post to this group.

                              Comment

                              Working...