|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
BinaryReader (et al) leave openShouldn't BinaryReader and BinaryWriter (or any stream that takes another
stream) have an overload to LeaveInnerStream open. bool leaveInnerStreamOpen = true; using(BinaryReader br = new BinaryReader(innerStream, leaveInnerStreamOpen)) { // Use the br stream, but don't close innerStream after Dispose. } That way you can pass stream around to helper methods that may wrap the stream in another stream and not close the first stream after the helper is done. -- William Stacey [MVP] William Stacey [MVP] <stac***@mvps.org> wrote:
> Shouldn't BinaryReader and BinaryWriter (or any stream that takes another Yes, they should. I've got a NonClosingStreamWrapper class for > stream) have an overload to LeaveInnerStream open. precisely this reason. See http://www.pobox.com/~skeet/csharp/miscutil It would be much nicer not to have to do the wrapping in the first place :) -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too Thanks Jon. I would think they could add this before 2.0 gets out the door.
One more constructor overload and a property and Dispose has to change. Not sure what that would break (If anything) however. -- Show quoteWilliam Stacey [MVP] "Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message news:MPG.1dab8e7bcc36886398c847@msnews.microsoft.com... > William Stacey [MVP] <stac***@mvps.org> wrote: >> Shouldn't BinaryReader and BinaryWriter (or any stream that takes another >> stream) have an overload to LeaveInnerStream open. > > Yes, they should. I've got a NonClosingStreamWrapper class for > precisely this reason. > > See http://www.pobox.com/~skeet/csharp/miscutil > > It would be much nicer not to have to do the wrapping in the first > place :) > > -- > Jon Skeet - <sk***@pobox.com> > http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet > If replying to the group, please do not mail me too "William Stacey [MVP]" <stac***@mvps.org> wrote in message It would make things a bit more difficult, one type has two different sets news:Oy9Fd0EyFHA.1032@TK2MSFTNGP12.phx.gbl... > Thanks Jon. I would think they could add this before 2.0 gets out the > door. One more constructor overload and a property and Dispose has to > change. Not sure what that would break (If anything) however. > of dispose semantics, so definitivly closing a file is a little harder. Not sure I understand Daniel. A FileStream for example, does not take a
stream in the constructor, so I don't have worry about closing an innerstream there. So that will not change. It is only when I "wrap" a FS (for example) in something like a TextWriter or BinaryWriter. In many cases, I don't want dispose on those streams to close the innerstream as I want control over that and close it when done. TMK, this does not change dispose semantics from the Users perspective as dispose still gets called as normal. -- Show quoteWilliam Stacey [MVP] "Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in message news:OsPDi$IyFHA.448@TK2MSFTNGP11.phx.gbl... > > "William Stacey [MVP]" <stac***@mvps.org> wrote in message > news:Oy9Fd0EyFHA.1032@TK2MSFTNGP12.phx.gbl... >> Thanks Jon. I would think they could add this before 2.0 gets out the >> door. One more constructor overload and a property and Dispose has to >> change. Not sure what that would break (If anything) however. >> > > It would make things a bit more difficult, one type has two different sets > of dispose semantics, so definitivly closing a file is a little harder. > William Stacey [MVP] <stac***@mvps.org> wrote:
> Thanks Jon. I would think they could add this before 2.0 gets out the door. I don't think so, to be honest.> One more constructor overload and a property and Dispose has to change. Not Indeed - there'd be a fair amount of testing needed.> sure what that would break (If anything) however. Maybe for 3.0... -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too > Shouldn't BinaryReader and BinaryWriter (or any stream that takes another try this:> stream) have an overload to LeaveInnerStream open. > > bool leaveInnerStreamOpen = true; > using(BinaryReader br = new BinaryReader(innerStream, > leaveInnerStreamOpen)) > { > // Use the br stream, but don't close innerStream after Dispose. > } BinaryReader br = new BinaryReader(innerStream, leaveInnerStreamOpen); // Use the br stream, but don't close innerStream after Dispose. the reason you would call Dispose() is if you want to release the inner resource, namely the stream. don't use using, the reader would still be collected but you won't have your stream closed!! Show quote > > That way you can pass stream around to helper methods that may wrap the > stream in another stream and not close the first stream after the helper > is done. > > -- > William Stacey [MVP] > > > The issue is BinaryReader does not currently have the "leaveInnerStreamOpen"
overload. So you can't code it that way. If you could, I would still use the Using clause to close the reader. It would just not close the innerstream itself. -- Show quoteWilliam Stacey [MVP] "Lloyd Dupont" <net.galador@ld> wrote in message news:uzNG76IyFHA.1256@TK2MSFTNGP09.phx.gbl... >> Shouldn't BinaryReader and BinaryWriter (or any stream that takes another >> stream) have an overload to LeaveInnerStream open. >> >> bool leaveInnerStreamOpen = true; >> using(BinaryReader br = new BinaryReader(innerStream, >> leaveInnerStreamOpen)) >> { >> // Use the br stream, but don't close innerStream after Dispose. >> } > > try this: > BinaryReader br = new BinaryReader(innerStream, leaveInnerStreamOpen); > // Use the br stream, but don't close innerStream after Dispose. > > the reason you would call Dispose() is if you want to release the inner > resource, namely the stream. > don't use using, the reader would still be collected but you won't have > your stream closed!! > > >> >> That way you can pass stream around to helper methods that may wrap the >> stream in another stream and not close the first stream after the helper >> is done. >> >> -- >> William Stacey [MVP] >> >> >> > > > The issue is BinaryReader does not currently have the Ask your self: what means closing the BinaryReader?> "leaveInnerStreamOpen" overload. So you can't code it that way. If you > could, I would still use the Using clause to close the reader. It would > just not close the innerstream itself. > A binary reader is nothing if itself if it doesn't have a Stream. Close it means nothing if not closing the underlying stream. I don't think they would ever had this constructor because: what's the point of disposing it if not disposing of the iner stream? I repeaat: Do't use using > Ask your self: what means closing the BinaryReader? BinaryReader is just a simple example. That said, the Dispose method in > > A binary reader is nothing if itself if it doesn't have a Stream. > Close it means nothing if not closing the underlying stream. > I don't think they would ever had this constructor because: what's the > point of disposing it if not disposing of the iner stream? BinaryReader does more then just close the innerstream. It also closes its internal state fields. You could imagine other more complex streams that *need to close down more stuff to close clean - regardless if it closes innerstream or not. Check the SslStream class for examples of this. > I don't think they would ever had this constructor because: what's the There may be other state you need to close as BinaryReader also sets a bunch > point of disposing it if not disposing of the inner stream? of flags. Look at the code. >I repeat: Do't use using I disagree. What is your argument.-- William Stacey [MVP] > I disagree. What is your argument. I disagree with you, what is the use of Dipose() anyway?Anyway as you are impervious to the voice of reson, I copy the code from BinaryReader.Dispose() below (coming straight out of reflector) and I would be keen to know why "it is important" to call Dispose() on it. protected virtual void Dispose(bool disposing) { if (disposing) { Stream stream1 = this.m_stream; this.m_stream = null; if (stream1 != null) { stream1.Close(); } } this.m_stream = null; this.m_buffer = null; this.m_decoder = null; this.m_charBytes = null; this.m_singleChar = null; this.m_charBuffer = null; } For the same reason you want to dispose of any object. You want its internal state to reflect it is disposed/closed. You don't want any future code that has a ref to the object to be able to call methods on the disposed stream (i.e. Read()). So I want to dispose of your wrapper stream, but you may not want to dispose of the innerstream - however you may want to Flush() it in the Dispose method like:
protected override void Dispose(bool disposing) { try { if (!disposing) { return; } if (this.leaveStreamOpen) { this.innerStream.Flush(); } else { this.innerStream.Close(); } } finally { base.Dispose(disposing); } }-- William Stacey [MVP] "Lloyd Dupont" <net.galador@ld> wrote in message news:e6c2W9JyFHA.1856@TK2MSFTNGP12.phx.gbl... I disagree with you, what is the use of Dipose() anyway?> I disagree. What is your argument. Anyway as you are impervious to the voice of reson, I copy the code from BinaryReader.Dispose() below (coming straight out of reflector) and I would be keen to know why "it is important" to call Dispose() on it. protected virtual void Dispose(bool disposing) { if (disposing) { Stream stream1 = this.m_stream; this.m_stream = null; if (stream1 != null) { stream1.Close(); } } this.m_stream = null; this.m_buffer = null; this.m_decoder = null; this.m_charBytes = null; this.m_singleChar = null; this.m_charBuffer = null; } oh yeah, Flush(), my bad :-(
so what of BinaryReader br = new BinraryReader(stream) // do stuff stream.Flush() here you go, achieve the desired result. doesn't it? "William Stacey [MVP]" <stac***@mvps.org> wrote in message news:eywO7MKyFHA.3856@tk2msftngp13.phx.gbl... For the same reason you want to dispose of any object. You want its internal state to reflect it is disposed/closed. You don't want any future code that has a ref to the object to be able to call methods on the disposed stream (i.e. Read()). So I want to dispose of your wrapper stream, but you may not want to dispose of the innerstream - however you may want to Flush() it in the Dispose method like:protected override void Dispose(bool disposing) { try { if (!disposing) { return; } if (this.leaveStreamOpen) { this.innerStream.Flush(); } else { this.innerStream.Close(); } } finally { base.Dispose(disposing); } }-- William Stacey [MVP] "Lloyd Dupont" <net.galador@ld> wrote in message news:e6c2W9JyFHA.1856@TK2MSFTNGP12.phx.gbl... I disagree with you, what is the use of Dipose() anyway?> I disagree. What is your argument. Anyway as you are impervious to the voice of reson, I copy the code from BinaryReader.Dispose() below (coming straight out of reflector) and I would be keen to know why "it is important" to call Dispose() on it. protected virtual void Dispose(bool disposing) { if (disposing) { Stream stream1 = this.m_stream; this.m_stream = null; if (stream1 != null) { stream1.Close(); } } this.m_stream = null; this.m_buffer = null; this.m_decoder = null; this.m_charBytes = null; this.m_singleChar = null; this.m_charBuffer = null; } No. Because when br goes out of scope and gets disposed it closes my stream. I don't want the stream disposed, hence the reason to topic started. What is needed is the leaveInnerStream switch. Remember innerstream could be a NetworkStream and I may have helper method that wrap that stream in a typical server program to operate on the NetworkStream. When these methods return they would close the NetworkStream unexpectedly.
-- William Stacey [MVP] "Lloyd Dupont" <net.galador@ld> wrote in message news:ODifYgKyFHA.3720@TK2MSFTNGP14.phx.gbl... oh yeah, Flush(), my bad :-(so what of BinaryReader br = new BinraryReader(stream) // do stuff stream.Flush() here you go, achieve the desired result. doesn't it? "William Stacey [MVP]" <stac***@mvps.org> wrote in message news:eywO7MKyFHA.3856@tk2msftngp13.phx.gbl... For the same reason you want to dispose of any object. You want its internal state to reflect it is disposed/closed. You don't want any future code that has a ref to the object to be able to call methods on the disposed stream (i.e. Read()). So I want to dispose of your wrapper stream, but you may not want to dispose of the innerstream - however you may want to Flush() it in the Dispose method like:protected override void Dispose(bool disposing) { try { if (!disposing) { return; } if (this.leaveStreamOpen) { this.innerStream.Flush(); } else { this.innerStream.Close(); } } finally { base.Dispose(disposing); } }-- William Stacey [MVP] "Lloyd Dupont" <net.galador@ld> wrote in message news:e6c2W9JyFHA.1856@TK2MSFTNGP12.phx.gbl... I disagree with you, what is the use of Dipose() anyway?> I disagree. What is your argument. Anyway as you are impervious to the voice of reson, I copy the code from BinaryReader.Dispose() below (coming straight out of reflector) and I would be keen to know why "it is important" to call Dispose() on it. protected virtual void Dispose(bool disposing) { if (disposing) { Stream stream1 = this.m_stream; this.m_stream = null; if (stream1 != null) { stream1.Close(); } } this.m_stream = null; this.m_buffer = null; this.m_decoder = null; this.m_charBytes = null; this.m_singleChar = null; this.m_charBuffer = null; } I refer you to the source code again
protected virtual void Dispose(bool disposing) { if (disposing) { Stream stream1 = this.m_stream; this.m_stream = null; if (stream1 != null) { stream1.Close(); } } this.m_stream = null; this.m_buffer = null; this.m_decoder = null; this.m_charBytes = null; this.m_singleChar = null; this.m_charBuffer = null; }the stream is close only if 'disposing' that means only if the reader has been disposed explicitely (as opposed to simply collected)"William Stacey [MVP]" <stac***@mvps.org> wrote in message news:%23lALdDLyFHA.736@tk2msftngp13.phx.gbl... No. Because when br goes out of scope and gets disposed it closes my stream. I don't want the stream disposed, hence the reason to topic started. What is needed is the leaveInnerStream switch. Remember innerstream could be a NetworkStream and I may have helper method that wrap that stream in a typical server program to operate on the NetworkStream. When these methods return they would close the NetworkStream unexpectedly.-- William Stacey [MVP] "Lloyd Dupont" <net.galador@ld> wrote in message news:ODifYgKyFHA.3720@TK2MSFTNGP14.phx.gbl... oh yeah, Flush(), my bad :-(so what of BinaryReader br = new BinraryReader(stream) // do stuff stream.Flush() here you go, achieve the desired result. doesn't it? "William Stacey [MVP]" <stac***@mvps.org> wrote in message news:eywO7MKyFHA.3856@tk2msftngp13.phx.gbl... For the same reason you want to dispose of any object. You want its internal state to reflect it is disposed/closed. You don't want any future code that has a ref to the object to be able to call methods on the disposed stream (i.e. Read()). So I want to dispose of your wrapper stream, but you may not want to dispose of the innerstream - however you may want to Flush() it in the Dispose method like:protected override void Dispose(bool disposing) { try { if (!disposing) { return; } if (this.leaveStreamOpen) { this.innerStream.Flush(); } else { this.innerStream.Close(); } } finally { base.Dispose(disposing); } }-- William Stacey [MVP] "Lloyd Dupont" <net.galador@ld> wrote in message news:e6c2W9JyFHA.1856@TK2MSFTNGP12.phx.gbl... I disagree with you, what is the use of Dipose() anyway?> I disagree. What is your argument. Anyway as you are impervious to the voice of reson, I copy the code from BinaryReader.Dispose() below (coming straight out of reflector) and I would be keen to know why "it is important" to call Dispose() on it. protected virtual void Dispose(bool disposing) { if (disposing) { Stream stream1 = this.m_stream; this.m_stream = null; if (stream1 != null) { stream1.Close(); } } this.m_stream = null; this.m_buffer = null; this.m_decoder = null; this.m_charBytes = null; this.m_singleChar = null; this.m_charBuffer = null; } William Stacey [MVP] <stac***@mvps.org> wrote:
> No. Because when br goes out of scope and gets disposed it closes my stream. It only gets disposed if you have a using statement, however. I don't believe BinaryReader has a finalizer, so that wouldn't dispose of it either. -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too William Stacey [MVP] wrote:
Show quote > Shouldn't BinaryReader and BinaryWriter (or any stream that takes another Hi,> stream) have an overload to LeaveInnerStream open. > > bool leaveInnerStreamOpen = true; > using(BinaryReader br = new BinaryReader(innerStream, leaveInnerStreamOpen)) > { > // Use the br stream, but don't close innerStream after Dispose. > } > > That way you can pass stream around to helper methods that may wrap the > stream in another stream and not close the first stream after the helper is > done. > > -- > William Stacey [MVP] Wouldn't this impose on these wrapper-streams additional constraints - such as the current seek position of the underlying stream? AFAIK, there are currently no such guarantees - precisely before it closes the stream when you finish with it, and it assumes once you pass it a stream that it is in complete control. That said, I believe all current implementations do leave the underlying stream at the "expected" position at all times. So you could probably interleave two readers on the same underlying stream (at least until you Dispose one...) Damien Damien |
|||||||||||||||||||||||