IDisposable, "using" keyword and "Close()" methods

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Willem van Rumpt

    IDisposable, "using" keyword and "Close()" methods

    Hi all,
    coming from an unmanaged programming background, I took my time to
    sort out the IDisposable and finalizer patterns. Just when I thought
    I had it all conceptually neatly arranged, the "Close()" methods reared
    their ugly (at least it would seem...)heads.

    I was happily delving away in the .NET framework, investigating the
    stream classes with the msdn and Lutz Roeder's .NET reflector, when I
    stumbled upon the following:

    (using BinaryReader as an example, though not the only "bad guy")
    1) The MSDN : "This implementation of Close calls the Dispose method
    passing a true value."
    2) the Close() method in the BinaryReader is marked virtual
    3) the "using" keyword will invoke the implemented IDisposable.Dis pose()
    on the expression you want to dispose

    it looks to me like the "using" keyword in this case could be
    potentially very dangerous. Nothing prevents me from descending from
    BinaryReader, override the Close() method, and do some essential extra
    work (marking a flag, log something, whatever), and everyone using my
    class with the "using" keyword would have (at best) unnoticed side effects.

    I can see the need for IDisposable, I can see the need for virtual
    methods that will call Dispose on your behalf, but I don't get the need
    for a "using" keyword for calling Dispose() for you, when (at least in
    some cases) you might be short-circuiting things because you should've
    called "Close()" (or whatever they choose to call it). The documentation
    in the MSDN doesn't mention anywhere (that is, I couldn't find it...)
    that you should use Close() instead of
    Dispose() from the implemented interface.

    Is (or should I mark) the "using" keyword "potentiall y dangerous"?

    Thanks in advance,

    Willem van Rumpt
  • Jon Skeet [C# MVP]

    #2
    Re: IDisposable, "using&quo t; keyword and "Close()&q uot; methods

    Willem van Rumpt <no.slide.spam@ no.thelandslide .spam.com> wrote:

    <snip>
    [color=blue]
    > Is (or should I mark) the "using" keyword "potentiall y dangerous"?[/color]

    No - failing to use "using" is potentially dangerous.

    If you want to write a class which doesn't implement Dispose
    appropriately - i.e. if calling Dispose isn't enough to clean up the
    unmanaged resources - that's fine. There's nothing to stop you from
    writing badly behaved classes in .NET - but it *is* relatively easy to
    write *well*-behaved classes instead.

    --
    Jon Skeet - <skeet@pobox.co m>
    Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

    If replying to the group, please do not mail me too

    Comment

    • Stoitcho Goutsev \(100\) [C# MVP]

      #3
      Re: IDisposable, &quot;using&quo t; keyword and &quot;Close()&q uot; methods

      Hi Willem,

      Close methods is added to stream, reader, writer, etc classes just because
      it makes more sense for those classes to be closed. Why is it virtual?
      Simply because normally when somethig work with streams the idea is to
      abstract where the data actually goes it could be memory, disk, db, etc. So
      normaly the code deals with the base class. In .NET disposing is the way to
      release unmanaged resources, so you should write your classes with that in
      mind.
      Some times Close behaves differently according to some conditions. For
      example look at the Form class. When the form is shown modalles calling
      Close dispose the form object. When the form is shown as a modal dialog,
      though, Close hides the form and doesn't destroyed (disposed) it.
      One is sure thing, though, Dispose always destroy. So bare this in mind when
      you write your classes

      --
      HTH
      Stoitcho Goutsev (100) [C# MVP]


      "Willem van Rumpt" <no.slide.spam@ no.thelandslide .spam.com> wrote in message
      news:uK7DSX0bEH A.2660@TK2MSFTN GP12.phx.gbl...[color=blue]
      > Hi all,
      > coming from an unmanaged programming background, I took my time to
      > sort out the IDisposable and finalizer patterns. Just when I thought
      > I had it all conceptually neatly arranged, the "Close()" methods reared
      > their ugly (at least it would seem...)heads.
      >
      > I was happily delving away in the .NET framework, investigating the
      > stream classes with the msdn and Lutz Roeder's .NET reflector, when I
      > stumbled upon the following:
      >
      > (using BinaryReader as an example, though not the only "bad guy")
      > 1) The MSDN : "This implementation of Close calls the Dispose method
      > passing a true value."
      > 2) the Close() method in the BinaryReader is marked virtual
      > 3) the "using" keyword will invoke the implemented IDisposable.Dis pose()
      > on the expression you want to dispose
      >
      > it looks to me like the "using" keyword in this case could be
      > potentially very dangerous. Nothing prevents me from descending from
      > BinaryReader, override the Close() method, and do some essential extra
      > work (marking a flag, log something, whatever), and everyone using my
      > class with the "using" keyword would have (at best) unnoticed side[/color]
      effects.[color=blue]
      >
      > I can see the need for IDisposable, I can see the need for virtual
      > methods that will call Dispose on your behalf, but I don't get the need
      > for a "using" keyword for calling Dispose() for you, when (at least in
      > some cases) you might be short-circuiting things because you should've
      > called "Close()" (or whatever they choose to call it). The documentation
      > in the MSDN doesn't mention anywhere (that is, I couldn't find it...)
      > that you should use Close() instead of
      > Dispose() from the implemented interface.
      >
      > Is (or should I mark) the "using" keyword "potentiall y dangerous"?
      >
      > Thanks in advance,
      >
      > Willem van Rumpt[/color]


      Comment

      • Willem van Rumpt

        #4
        Re: IDisposable, &quot;using&quo t; keyword and &quot;Close()&q uot; methods

        Jon Skeet [C# MVP] wrote:
        [color=blue]
        > Willem van Rumpt <no.slide.spam@ no.thelandslide .spam.com> wrote:
        >
        > <snip>
        >[color=green]
        >>Is (or should I mark) the "using" keyword "potentiall y dangerous"?[/color]
        >
        >
        > No - failing to use "using" is potentially dangerous.
        >
        > If you want to write a class which doesn't implement Dispose
        > appropriately - i.e. if calling Dispose isn't enough to clean up the
        > unmanaged resources - that's fine. There's nothing to stop you from
        > writing badly behaved classes in .NET - but it *is* relatively easy to
        > write *well*-behaved classes instead.
        >[/color]
        I'm not talking unmanaged resources. I'm assuming that the Dispose()
        part would be properly implemented, i.e. releasing all unmanaged
        resources, BUT since the Close() method is virtual, it seems the class
        can still work and have a function and a state which the Close() method
        sets or invokes, which would not be invoked or set if using the "using"
        keyword, even more, it has been explicitly marked "virtual" so
        descendants can do their own thing before/after calling dispose.

        From what you say, I think that I didn't grasp the meaning of
        IDisposable correctly. Should I regard a "disposable " object as
        "destroyed" , not to be referenced again?.

        Willem van Rumpt

        Comment

        • Sunny

          #5
          Re: IDisposable, &quot;using&quo t; keyword and &quot;Close()&q uot; methods

          Hi,

          Just override Dispose(bool) and there put your code. Like this:

          using System;
          using System.IO;

          namespace Test {

          public class TestReader : BinaryReader {

          public TestReader(Stre am stream) : base(stream)
          {
          }

          protected override void Dispose(bool disposing)
          {
          Console.WriteLi ne("Dispose called.");
          base.Dispose(di sposing);
          }
          }

          public class Test {
          [STAThread]
          public static void Main()
          {
          TestReader testReader = new TestReader(new MemoryStream()) ;
          testReader.Clos e();
          }
          }
          }

          Sunny

          In article <uK7DSX0bEHA.26 60@TK2MSFTNGP12 .phx.gbl>,
          no.slide.spam@n o.thelandslide. spam.com says...[color=blue]
          > Hi all,
          > coming from an unmanaged programming background, I took my time to
          > sort out the IDisposable and finalizer patterns. Just when I thought
          > I had it all conceptually neatly arranged, the "Close()" methods reared
          > their ugly (at least it would seem...)heads.
          >
          > I was happily delving away in the .NET framework, investigating the
          > stream classes with the msdn and Lutz Roeder's .NET reflector, when I
          > stumbled upon the following:
          >
          > (using BinaryReader as an example, though not the only "bad guy")
          > 1) The MSDN : "This implementation of Close calls the Dispose method
          > passing a true value."
          > 2) the Close() method in the BinaryReader is marked virtual
          > 3) the "using" keyword will invoke the implemented IDisposable.Dis pose()
          > on the expression you want to dispose
          >
          > it looks to me like the "using" keyword in this case could be
          > potentially very dangerous. Nothing prevents me from descending from
          > BinaryReader, override the Close() method, and do some essential extra
          > work (marking a flag, log something, whatever), and everyone using my
          > class with the "using" keyword would have (at best) unnoticed side effects.
          >
          > I can see the need for IDisposable, I can see the need for virtual
          > methods that will call Dispose on your behalf, but I don't get the need
          > for a "using" keyword for calling Dispose() for you, when (at least in
          > some cases) you might be short-circuiting things because you should've
          > called "Close()" (or whatever they choose to call it). The documentation
          > in the MSDN doesn't mention anywhere (that is, I couldn't find it...)
          > that you should use Close() instead of
          > Dispose() from the implemented interface.
          >
          > Is (or should I mark) the "using" keyword "potentiall y dangerous"?
          >
          > Thanks in advance,
          >
          > Willem van Rumpt
          >[/color]

          Comment

          • Jon Skeet [C# MVP]

            #6
            Re: IDisposable, &quot;using&quo t; keyword and &quot;Close()&q uot; methods

            Willem van Rumpt <no.slide.spam@ no.thelandslide .spam.com> wrote:[color=blue][color=green]
            > > If you want to write a class which doesn't implement Dispose
            > > appropriately - i.e. if calling Dispose isn't enough to clean up the
            > > unmanaged resources - that's fine. There's nothing to stop you from
            > > writing badly behaved classes in .NET - but it *is* relatively easy to
            > > write *well*-behaved classes instead.[/color]
            >
            > I'm not talking unmanaged resources. I'm assuming that the Dispose()
            > part would be properly implemented, i.e. releasing all unmanaged
            > resources, BUT since the Close() method is virtual, it seems the class
            > can still work and have a function and a state which the Close() method
            > sets or invokes, which would not be invoked or set if using the "using"
            > keyword, even more, it has been explicitly marked "virtual" so
            > descendants can do their own thing before/after calling dispose.[/color]

            For some classes, there may be things you can do with an object after
            calling Close, but before calling Dispose.

            It's interesting to note that Stream is rather different from
            BinaryWriter - Dispose calls Close rather than the other way round.
            [color=blue]
            > From what you say, I think that I didn't grasp the meaning of
            > IDisposable correctly. Should I regard a "disposable " object as
            > "destroyed" , not to be referenced again?.[/color]

            When an object is disposed, it should usually either be ready to reuse
            "from scratch" or shouldn't be reused at all - usually the latter.
            Calling Dispose should be all that is required when one is finished
            with an object, and it's very rare (IME) that it's good to call it
            *before* one is finished with the object.

            --
            Jon Skeet - <skeet@pobox.co m>
            Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

            If replying to the group, please do not mail me too

            Comment

            • Kyril Magnos

              #7
              Re: IDisposable, &quot;using&quo t; keyword and &quot;Close()&q uot; methods

              LMFAO!!!

              --
              HTH

              Kyril Magnos

              "Richard" <Richard@discus sions.microsoft .com> wrote in message
              news:C4041360-B473-400F-91FF-B1DE382FD23F@mi crosoft.com...
              |> Nothing prevents me from descending from
              | > BinaryReader, override the Close() method, and do some essential extra
              | > work (marking a flag, log something, whatever), and everyone using my
              | > class with the "using" keyword would have (at best) unnoticed side
              effects.
              | >
              |
              | The IDisposable pattern wants you to do all of your extra work in the
              overriden method aka "protected override void Dispose(bool disposing)". If
              you put your extra work in there then the "using" keyword will work fine as
              the keyword is going to call "void Dispose()" witch is implemented to call
              your overriden "Dispose(tr ue)" - hence doing your extra work...
              |
              | > Is (or should I mark) the "using" keyword "potentiall y dangerous"?
              | >
              |
              | Don't forget that "using" is syntactically equivalent to try{}
              finally{Dispose } so it's a good idea to use it. Actually I think the whole
              IDispose thing is LAAAAMMMMMEEE! As a C++ guy I really really want a .NET
              keyword "delete" that is defined as: immediately calls the object's
              finalizer {if one exists} and then issues a GC.SuppressFina lizer() for the
              object...
              |
              | But nooo nobody listens to me... Nope! I thought going into Iraq was a
              dumb idea - all I wanted to do was confiscate Saudi Arabian oil and kick the
              natives out into their endless beach. If we'd done that gas would be .10
              per gallon, we would have flipped UBL the big time finger by confiscating
              holy land, the Wahhabiist movement would have lost its funding, and we'd
              have a HUGE base right next to Saddam Hussein while leaving HIM in token
              power so that he can deal with the Iraqi people. But nooooo.... I get no
              delete keyword and now I'm stuck with an estimated $30,000 per taxpayer bill
              for a dumb headed plan to make the middle east safe for Israel....
              |
              | Nope nobody ever listens to me and that's why the world's a Flippin
              mess...
              |
              |
              |
              |
              |


              Comment

              • Jon Skeet [C# MVP]

                #8
                RE: IDisposable, &quot;using&quo t; keyword and &quot;Close()&q uot; methods

                Richard <Richard@discus sions.microsoft .com> wrote:[color=blue]
                > Don't forget that "using" is syntactically equivalent to try{}
                > finally{Dispose } so it's a good idea to use it. Actually I think the
                > whole IDispose thing is LAAAAMMMMMEEE! As a C++ guy I really really
                > want a .NET keyword "delete" that is defined as: immediately calls
                > the object's finalizer {if one exists} and then issues a
                > GC.SuppressFina lizer() for the object...[/color]

                That doesn't allow for situations where an object can be reused, of
                course, which Dispose allows for in theory, even if it's rarely used.

                You'd also still want another keyword in order to put the delete within
                a try/finally block automatically, IMO.

                --
                Jon Skeet - <skeet@pobox.co m>
                Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

                If replying to the group, please do not mail me too

                Comment

                Working...