BinaryWriter/Reader question

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Filip Strugar

    BinaryWriter/Reader question


    Considering that the BinaryWriter/BinaryReader object closes the underlaying
    stream upon being gc collected, is the following code correct, and if it is
    what is the reason preventing BinaryWriter object garbage collection after
    the WriteSomething method is executed?

    ----

    using System;
    using System.IO;

    namespace Test
    {
    class Test
    {
    static void Main(string[] args)
    {
    using (Stream output = (Stream)File.Op enWrite("test.t xt"))
    {
    WriteSomething( output);
    WriteSomethingE lse(output);
    }
    }

    static void WriteSomething( Stream outputStream)
    {
    BinaryWriter writer = new BinaryWriter(ou tputStream);
    writer.Write("S omething");
    }

    static void WriteSomethingE lse(Stream outputStream)
    {
    BinaryWriter writer = new BinaryWriter(ou tputStream);
    writer.Write("S omethingElse");
    }
    }
    }

    ---


  • Guest's Avatar

    #2
    Re: BinaryWriter/Reader question

    Your code looks fine. Nothing prevents the garbage collector from collecting
    the BinaryWriter in WriteSomething( ). Why do you care? It's out of scope at
    that point.

    It has no Finalize() method, so nothing is going to happen when it gets
    collected anyway.

    Pete


    "Filip Strugar" <fili@sezampro_ dot_yu> wrote in message
    news:eHHolvOREH A.3728@TK2MSFTN GP10.phx.gbl...[color=blue]
    >
    > Considering that the BinaryWriter/BinaryReader object closes the[/color]
    underlaying[color=blue]
    > stream upon being gc collected, is the following code correct, and if it[/color]
    is[color=blue]
    > what is the reason preventing BinaryWriter object garbage collection after
    > the WriteSomething method is executed?
    >
    > ----
    >
    > using System;
    > using System.IO;
    >
    > namespace Test
    > {
    > class Test
    > {
    > static void Main(string[] args)
    > {
    > using (Stream output = (Stream)File.Op enWrite("test.t xt"))
    > {
    > WriteSomething( output);
    > WriteSomethingE lse(output);
    > }
    > }
    >
    > static void WriteSomething( Stream outputStream)
    > {
    > BinaryWriter writer = new BinaryWriter(ou tputStream);
    > writer.Write("S omething");
    > }
    >
    > static void WriteSomethingE lse(Stream outputStream)
    > {
    > BinaryWriter writer = new BinaryWriter(ou tputStream);
    > writer.Write("S omethingElse");
    > }
    > }
    > }
    >
    > ---
    >
    >[/color]


    Comment

    • Filip Strugar

      #3
      Re: BinaryWriter/Reader question

      Will it get disposed?
      When BinaryWriter/Reader gets disposed, it closes the underlying stream, so
      no further writing (reading) on it is possible!

      <pdavis68@hotma il.com> wrote in message
      news:19e230b406 8fc9df2751fd824 9eb3b59@news.me ganetnews.com.. .[color=blue]
      > Your code looks fine. Nothing prevents the garbage collector from[/color]
      collecting[color=blue]
      > the BinaryWriter in WriteSomething( ). Why do you care? It's out of scope[/color]
      at[color=blue]
      > that point.
      >
      > It has no Finalize() method, so nothing is going to happen when it gets
      > collected anyway.
      >
      > Pete
      >
      >
      > "Filip Strugar" <fili@sezampro_ dot_yu> wrote in message
      > news:eHHolvOREH A.3728@TK2MSFTN GP10.phx.gbl...[color=green]
      > >
      > > Considering that the BinaryWriter/BinaryReader object closes the[/color]
      > underlaying[color=green]
      > > stream upon being gc collected, is the following code correct, and if it[/color]
      > is[color=green]
      > > what is the reason preventing BinaryWriter object garbage collection[/color][/color]
      after[color=blue][color=green]
      > > the WriteSomething method is executed?
      > >
      > > ----
      > >
      > > using System;
      > > using System.IO;
      > >
      > > namespace Test
      > > {
      > > class Test
      > > {
      > > static void Main(string[] args)
      > > {
      > > using (Stream output = (Stream)File.Op enWrite("test.t xt"))
      > > {
      > > WriteSomething( output);
      > > WriteSomethingE lse(output);
      > > }
      > > }
      > >
      > > static void WriteSomething( Stream outputStream)
      > > {
      > > BinaryWriter writer = new BinaryWriter(ou tputStream);
      > > writer.Write("S omething");
      > > }
      > >
      > > static void WriteSomethingE lse(Stream outputStream)
      > > {
      > > BinaryWriter writer = new BinaryWriter(ou tputStream);
      > > writer.Write("S omethingElse");
      > > }
      > > }
      > > }
      > >
      > > ---
      > >
      > >[/color]
      >
      >[/color]


      Comment

      • Jon Skeet [C# MVP]

        #4
        Re: BinaryWriter/Reader question

        Filip Strugar <fili@sezampro_ dot_yu> wrote:[color=blue]
        > Will it get disposed?
        > When BinaryWriter/Reader gets disposed, it closes the underlying stream, so
        > no further writing (reading) on it is possible![/color]

        It would only be Disposed if you *told* it to be Disposed, either with
        an explicit call or with a using statement (or another method call
        which called it).

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

        • Guest's Avatar

          #5
          Re: BinaryWriter/Reader question

          As Jon pointed out, it's only disposed if you explicitly call the Dispose
          method. But in the case of BinaryWriter, Dispose() is a protected member, so
          you'd only call it from a derived class anyway. And even then, if you call
          Dispose(false), the underlying stream won't be closed.

          The implementation of the Dispose() method in BinaryWriter simply checks to
          see if Disposing() is true. If it is, then it closes the underlying stream.
          Otherwise it does nothing.

          Pete


          "Filip Strugar" <fili@sezampro_ dot_yu> wrote in message
          news:eSFlO4QREH A.2704@TK2MSFTN GP10.phx.gbl...[color=blue]
          > Will it get disposed?
          > When BinaryWriter/Reader gets disposed, it closes the underlying stream,[/color]
          so[color=blue]
          > no further writing (reading) on it is possible!
          >
          > <pdavis68@hotma il.com> wrote in message
          > news:19e230b406 8fc9df2751fd824 9eb3b59@news.me ganetnews.com.. .[color=green]
          > > Your code looks fine. Nothing prevents the garbage collector from[/color]
          > collecting[color=green]
          > > the BinaryWriter in WriteSomething( ). Why do you care? It's out of scope[/color]
          > at[color=green]
          > > that point.
          > >
          > > It has no Finalize() method, so nothing is going to happen when it gets
          > > collected anyway.
          > >
          > > Pete
          > >
          > >
          > > "Filip Strugar" <fili@sezampro_ dot_yu> wrote in message
          > > news:eHHolvOREH A.3728@TK2MSFTN GP10.phx.gbl...[color=darkred]
          > > >
          > > > Considering that the BinaryWriter/BinaryReader object closes the[/color]
          > > underlaying[color=darkred]
          > > > stream upon being gc collected, is the following code correct, and if[/color][/color][/color]
          it[color=blue][color=green]
          > > is[color=darkred]
          > > > what is the reason preventing BinaryWriter object garbage collection[/color][/color]
          > after[color=green][color=darkred]
          > > > the WriteSomething method is executed?
          > > >
          > > > ----
          > > >
          > > > using System;
          > > > using System.IO;
          > > >
          > > > namespace Test
          > > > {
          > > > class Test
          > > > {
          > > > static void Main(string[] args)
          > > > {
          > > > using (Stream output = (Stream)File.Op enWrite("test.t xt"))
          > > > {
          > > > WriteSomething( output);
          > > > WriteSomethingE lse(output);
          > > > }
          > > > }
          > > >
          > > > static void WriteSomething( Stream outputStream)
          > > > {
          > > > BinaryWriter writer = new BinaryWriter(ou tputStream);
          > > > writer.Write("S omething");
          > > > }
          > > >
          > > > static void WriteSomethingE lse(Stream outputStream)
          > > > {
          > > > BinaryWriter writer = new BinaryWriter(ou tputStream);
          > > > writer.Write("S omethingElse");
          > > > }
          > > > }
          > > > }
          > > >
          > > > ---
          > > >
          > > >[/color]
          > >
          > >[/color]
          >
          >[/color]


          Comment

          • Jon Skeet [C# MVP]

            #6
            Re: BinaryWriter/Reader question

            <pdavis68@hotma il.com> wrote:[color=blue]
            > As Jon pointed out, it's only disposed if you explicitly call the Dispose
            > method. But in the case of BinaryWriter, Dispose() is a protected member, so
            > you'd only call it from a derived class anyway.[/color]

            No, Dispose(bool) is a protected member, but just Dispose() isn't - and
            that's what you'd usually call. It calls Dispose(true).

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

            • Guest's Avatar

              #7
              Re: BinaryWriter/Reader question

              BinaryWriter only has the Dispose(bool). It does not have a Dispose() method
              without parameters.

              Pete

              "Jon Skeet [C# MVP]" <skeet@pobox.co m> wrote in message
              news:MPG.1b22ac 4c9969277c98aa6 e@msnews.micros oft.com...[color=blue]
              > <pdavis68@hotma il.com> wrote:[color=green]
              > > As Jon pointed out, it's only disposed if you explicitly call the[/color][/color]
              Dispose[color=blue][color=green]
              > > method. But in the case of BinaryWriter, Dispose() is a protected[/color][/color]
              member, so[color=blue][color=green]
              > > you'd only call it from a derived class anyway.[/color]
              >
              > No, Dispose(bool) is a protected member, but just Dispose() isn't - and
              > that's what you'd usually call. It calls Dispose(true).
              >
              > --
              > Jon Skeet - <skeet@pobox.co m>
              > http://www.pobox.com/~skeet
              > If replying to the group, please do not mail me too[/color]


              Comment

              • Guest's Avatar

                #8
                Re: BinaryWriter/Reader question

                Hmm, this is strange.

                BinaryWriter is from IDisposable, but I can't find the implementation of the
                Dispose() method.

                What's that all about? There's no Dispose() method documented. Reflector
                shows no implementation of Dispose(). It doesn't show up in intellisense...
                What's the deal?

                How can it derive from IDisposable and not implement Dispose()?

                Pete

                <pdavis68@hotma il.com> wrote in message
                news:8536a5ef02 457ba84b936e7ba c1cc714@news.me ganetnews.com.. .[color=blue]
                > BinaryWriter only has the Dispose(bool). It does not have a Dispose()[/color]
                method[color=blue]
                > without parameters.
                >
                > Pete
                >
                > "Jon Skeet [C# MVP]" <skeet@pobox.co m> wrote in message
                > news:MPG.1b22ac 4c9969277c98aa6 e@msnews.micros oft.com...[color=green]
                > > <pdavis68@hotma il.com> wrote:[color=darkred]
                > > > As Jon pointed out, it's only disposed if you explicitly call the[/color][/color]
                > Dispose[color=green][color=darkred]
                > > > method. But in the case of BinaryWriter, Dispose() is a protected[/color][/color]
                > member, so[color=green][color=darkred]
                > > > you'd only call it from a derived class anyway.[/color]
                > >
                > > No, Dispose(bool) is a protected member, but just Dispose() isn't - and
                > > that's what you'd usually call. It calls Dispose(true).
                > >
                > > --
                > > Jon Skeet - <skeet@pobox.co m>
                > > http://www.pobox.com/~skeet
                > > If replying to the group, please do not mail me too[/color]
                >
                >[/color]


                Comment

                • Jon Skeet [C# MVP]

                  #9
                  Re: BinaryWriter/Reader question

                  <pdavis68@hotma il.com> wrote:[color=blue]
                  > BinaryWriter only has the Dispose(bool). It does not have a Dispose() method
                  > without parameters.[/color]

                  Yes it does. It has to - it implements IDisposable. However, it
                  implements it using explicit interface implementation, so you have to
                  cast to IDisposable (or use a using statement):

                  BinaryWriter foo = new BinaryWriter(.. .);
                  ....
                  ((IDisposable)f oo).Dispose();

                  or

                  using (BinaryWriter foo = new BinaryWriter(.. .))
                  {
                  ....
                  }

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

                  • Guest's Avatar

                    #10
                    Re: BinaryWriter/Reader question

                    Okay, I see how it works now. I didn't see the Dispose method because I was
                    looking at the methods in alphabetical order and it falls under
                    System.IDisposa ble.Dispose().

                    Thanks for clearing that up.


                    Now, what seems strange is the implementation is:

                    private void System.IDisposa ble.Dispose()
                    {
                    this.Dispose(tr ue);
                    }

                    If it's declared private, how can I call it (which I can, I verified your
                    typecasting code works).

                    Pete

                    P.S. thanks for the education here.


                    "Jon Skeet [C# MVP]" <skeet@pobox.co m> wrote in message
                    news:MPG.1b22b2 cb1446ec7d98aa6 f@msnews.micros oft.com...[color=blue]
                    > <pdavis68@hotma il.com> wrote:[color=green]
                    > > BinaryWriter only has the Dispose(bool). It does not have a Dispose()[/color][/color]
                    method[color=blue][color=green]
                    > > without parameters.[/color]
                    >
                    > Yes it does. It has to - it implements IDisposable. However, it
                    > implements it using explicit interface implementation, so you have to
                    > cast to IDisposable (or use a using statement):
                    >
                    > BinaryWriter foo = new BinaryWriter(.. .);
                    > ...
                    > ((IDisposable)f oo).Dispose();
                    >
                    > or
                    >
                    > using (BinaryWriter foo = new BinaryWriter(.. .))
                    > {
                    > ...
                    > }
                    >
                    > --
                    > Jon Skeet - <skeet@pobox.co m>
                    > http://www.pobox.com/~skeet
                    > If replying to the group, please do not mail me too[/color]


                    Comment

                    • Jon Skeet [C# MVP]

                      #11
                      Re: BinaryWriter/Reader question

                      <pdavis68@hotma il.com> wrote:[color=blue]
                      > Now, what seems strange is the implementation is:
                      >
                      > private void System.IDisposa ble.Dispose()
                      > {
                      > this.Dispose(tr ue);
                      > }
                      >
                      > If it's declared private, how can I call it (which I can, I verified your
                      > typecasting code works).
                      >
                      > Pete
                      >
                      > P.S. thanks for the education here.[/color]

                      Explicit interface implementation is strange like that. It's sort of
                      private, sort of public. See

                      Hi. I'm Jon Jagger, director of software at Kosli. I built cyber-dojo, the place teams practice programming.


                      for more information.

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

                      • Guest's Avatar

                        #12
                        Re: BinaryWriter/Reader question

                        Thanks. That was really informative. I can see how that would be useful from
                        time to time.

                        I think we can assume that it was implemented this way in BinaryWriter
                        because of the first justification (Paragraph 5)

                        "This is particularly useful when a class or struct implements an internal
                        interface that is of no interest to a consumer of that class or struct. "

                        The other justifcation being to disambiguate interface members with the same
                        signature, which wouldn't be the case here.

                        The ability to make it publicly accessible would be for justification #2 it
                        seems, so in this particular case, can I assume that calling Dispose()
                        directly would be a bad idea?

                        Thanks again. This has been really englightening, albeit in a somewhat
                        obscure area of C#.

                        Pete

                        "Jon Skeet [C# MVP]" <skeet@pobox.co m> wrote in message
                        news:MPG.1b22d2 d635e4e19898aa7 0@msnews.micros oft.com...[color=blue]
                        > <pdavis68@hotma il.com> wrote:[color=green]
                        > > Now, what seems strange is the implementation is:
                        > >
                        > > private void System.IDisposa ble.Dispose()
                        > > {
                        > > this.Dispose(tr ue);
                        > > }
                        > >
                        > > If it's declared private, how can I call it (which I can, I verified[/color][/color]
                        your[color=blue][color=green]
                        > > typecasting code works).
                        > >
                        > > Pete
                        > >
                        > > P.S. thanks for the education here.[/color]
                        >
                        > Explicit interface implementation is strange like that. It's sort of
                        > private, sort of public. See
                        >
                        > http://www.jaggersoft.com/csharp_standard/20.4.1.htm
                        >
                        > for more information.
                        >
                        > --
                        > Jon Skeet - <skeet@pobox.co m>
                        > http://www.pobox.com/~skeet
                        > If replying to the group, please do not mail me too[/color]


                        Comment

                        • Jon Skeet [C# MVP]

                          #13
                          Re: BinaryWriter/Reader question

                          <pdavis68@hotma il.com> wrote:[color=blue]
                          > Thanks. That was really informative. I can see how that would be useful from
                          > time to time.[/color]

                          Personally I think it's much more rarely useful than MS seems to...
                          [color=blue]
                          > I think we can assume that it was implemented this way in BinaryWriter
                          > because of the first justification (Paragraph 5)
                          >
                          > "This is particularly useful when a class or struct implements an internal
                          > interface that is of no interest to a consumer of that class or struct. "[/color]

                          I'm not sure - it seems as natural to me to want to Dispose of a
                          BinaryWriter as (say) a StreamWriter. They're both just wrappers round
                          streams which add value.
                          [color=blue]
                          > The other justifcation being to disambiguate interface members with the same
                          > signature, which wouldn't be the case here.
                          >
                          > The ability to make it publicly accessible would be for justification #2 it
                          > seems, so in this particular case, can I assume that calling Dispose()
                          > directly would be a bad idea?[/color]

                          Not at all - it's something I'd do as a matter of course:

                          using (Stream stream = ...)
                          {
                          using (BinaryWriter writer = ...)
                          {
                          ...
                          }
                          }

                          I *always* dispose of *everything* which implements IDisposable and of
                          which I have direct knowledge of the useful lifetime.
                          [color=blue]
                          > Thanks again. This has been really englightening, albeit in a somewhat
                          > obscure area of C#.[/color]

                          Glad it's helped :)

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

                          • Guest's Avatar

                            #14
                            Re: BinaryWriter/Reader question

                            > > The ability to make it publicly accessible would be for justification #2
                            it[color=blue][color=green]
                            > > seems, so in this particular case, can I assume that calling Dispose()
                            > > directly would be a bad idea?[/color]
                            >
                            > Not at all - it's something I'd do as a matter of course:
                            >[/color]
                            Yes, but in the example originally offered by Flip, where the person created
                            the stream in one method, then called two separate methods that created
                            BinaryWriters against that stream, if the person were to call Dispose() on
                            the BinaryWriter in the first method, it would have closed the stream prior
                            to the second method being called.

                            Obviously, in this case, calling Dispose() would cause the program to fail
                            in the second method call.

                            I guess in this case, it helps to know what's going on underneath, but I
                            would infer that the fact that Dispose() is implemented this way and
                            furthermore, that Dispose() isn't even documented for the BinaryWriter, that
                            calling Dispose() on the BinaryWriter is probably not always a good idea.

                            Besides, all it does is close the Stream which is going to happen anyway.
                            But again, without knowing the underlying implementation and without it
                            being documented, this wouldn't be known (except for the fact that
                            unobfuscated code is so easy to reverse engineer in .NET).

                            Actually, I have never used "using" except for accessing namespaces myself.
                            I don't doubt its usefulness nor its readability. Simply haven't adopted it
                            as part of my programming style.... yet....

                            Pete

                            Pete


                            Comment

                            • Jon Skeet [C# MVP]

                              #15
                              Re: BinaryWriter/Reader question

                              <pdavis68@hotma il.com> wrote:[color=blue][color=green][color=darkred]
                              > > > The ability to make it publicly accessible would be for justification #2[/color][/color]
                              > it[color=green][color=darkred]
                              > > > seems, so in this particular case, can I assume that calling Dispose()
                              > > > directly would be a bad idea?[/color]
                              > >
                              > > Not at all - it's something I'd do as a matter of course:[/color][/color]
                              [color=blue]
                              > Yes, but in the example originally offered by Flip, where the person created
                              > the stream in one method, then called two separate methods that created
                              > BinaryWriters against that stream, if the person were to call Dispose() on
                              > the BinaryWriter in the first method, it would have closed the stream prior
                              > to the second method being called.[/color]

                              Yup.
                              [color=blue]
                              > Obviously, in this case, calling Dispose() would cause the program to fail
                              > in the second method call.[/color]

                              Indeed. The same would be true for StreamWriter, too. I've always
                              thought it would be nice to have some way of constructing those objects
                              so that the stream could be "detached" from the wrapper. That would
                              make it very clear what's involved.
                              [color=blue]
                              > I guess in this case, it helps to know what's going on underneath, but I
                              > would infer that the fact that Dispose() is implemented this way and
                              > furthermore, that Dispose() isn't even documented for the BinaryWriter
                              > that calling Dispose() on the BinaryWriter is probably not always a good idea.[/color]

                              It's not *always* a good idea (as in this case) but I believe that when
                              you know the lifetime of the stream as well, it's a good idea, just
                              going along with the idea that it implements IDisposable for a reason.

                              BinaryWriter.ID isposable.Dispo se actually *is* documented, but as "This
                              member supports the .NET Framework infrastructure and is not intended
                              to be used directly from your code." I think this is a *big* mistake,
                              and breaks the whole idea of interfaces.
                              [color=blue]
                              > Besides, all it does is close the Stream which is going to happen anyway.[/color]

                              It's going to happen at *some* stage, sure. I just think that getting
                              into the habit of disposing of objects which implement IDisposable and
                              thinking about the consequences of doing so is a good habit to get
                              into.
                              [color=blue]
                              > But again, without knowing the underlying implementation and without it
                              > being documented, this wouldn't be known (except for the fact that
                              > unobfuscated code is so easy to reverse engineer in .NET).
                              >
                              > Actually, I have never used "using" except for accessing namespaces
                              > myself. I don't doubt its usefulness nor its readability. Simply
                              > haven't adopted it as part of my programming style.... yet....[/color]

                              I would seriously consider doing so in the *very* near future. Are you
                              currently closing streams etc in finally blocks? If not, you're risking
                              problems if an exception is thrown. If you are, then your code would
                              become more readable immediately by using the using statement.

                              --
                              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...