30

I have one method that receives a Stream to write on it using a BinaryWriter. But when I dispose this BinaryWriter it also closes the stream. Can I leave it undisposed so I can leave my stream open?

Jader Dias
  • 88,211
  • 155
  • 421
  • 625

4 Answers4

59

As of .NET 4.5, the BinaryWriter class has a new constructor that takes a boolean parameter to indicate whether to leave the stream open or not.

Ref: http://msdn.microsoft.com/en-us/library/gg712841.aspx

public BinaryWriter(
    Stream output,
    Encoding encoding,
    bool leaveOpen
)
John K
  • 28,441
  • 31
  • 139
  • 229
Dave Van den Eynde
  • 17,020
  • 7
  • 59
  • 90
  • 1
    @JaderDias I know this is forever ago, but you should consider marking this as the answer. – Jamie Dec 29 '20 at 04:02
21

In the case of BinaryWriter, that isn't a direct option (although some stream wrappers do allow you to control this, for example GZipStream etc).

Jon has a NonClosingStreamWrapper in MiscUtil which should work: you wrap your stream in the non-closing wrapper, and give the wrapper to BinaryWriter. This essentially passes through everything except Close() and Dispose().

UnkwnTech
  • 88,102
  • 65
  • 184
  • 229
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Dont you think that there is a bit of hack? You suggest to change behavior(and assumtions) of the BinnaryWriter by fooling it with wrapper? – Mike Chaliy Jul 05 '09 at 22:24
  • 2
    No, that changes nothing **at all** related with `BinaryWriter`; it writes values to a stream and tells the stream when it is finished. Care to expand on what you have in mind? It is certainly *a lot* less hacky than not disposing something that is IDisposable on the grounds that you peeked at the implementation and decided to overrule it... – Marc Gravell Jul 05 '09 at 22:35
  • 1
    this changes expected behaviour of the binnary writer. because of expected behaviour of close and dispose operations, binnarywriter does not bother to flash. By filtering close and dispose functions you simply introduce bug that in cirtan circumstances hard to find. – Mike Chaliy Jul 06 '09 at 07:27
  • 3
    When a BinaryWriter closes, it flushes **itself** and tells the stream to close; with the wrapper, it would still flush itself. The difference it that the *stream* doesn't close. – Marc Gravell Jul 10 '09 at 22:48
  • Why does the NonClosingStreamWrapper throw an InvalidOperationException instead of an ObjectDisposedException after it is closed? – MarkusSchaber Jan 19 '12 at 17:03
  • @MarkusSchaber feel free to edit it locally; I didn't write it :p – Marc Gravell Jan 19 '12 at 17:09
9

Just do not call Dispose, use Flush instead, its safe.

Mike Chaliy
  • 25,801
  • 18
  • 67
  • 105
  • Yeah, I checked that on Reflector and it's true. – Jader Dias Jul 05 '09 at 21:04
  • 5
    It's safe _today_. Are you going to use Reflector on ever release of .NET to make sure it continues to be safe? This is not a solution. -1. – John Saunders Jul 05 '09 at 21:05
  • 2
    It will be always safe. Just because of writer semantics. Just think why it has dispose for now (hint look at examples on msdn). Also note that this is not the only place in .NET that incorrectly use IDisposable, for example well know Dispose problem with WCF channels. – Mike Chaliy Jul 05 '09 at 21:12
  • I can say more, @Marc Gravell will fail the same way if Microsoft will change semantics of the Dispose in BinnaryWriter. – Mike Chaliy Jul 05 '09 at 21:14
  • 1
    It has a dispose because it is assumed that it now owns the stream's lifetime. But if we don't want that, then I'd argue the correct thing to do is to separate the two - not hack how we use the writer. The writer is disposable; we should dispose it. In short, I disagree. – Marc Gravell Jul 05 '09 at 21:48
  • 1
    It has dispose just because ONE of the usage scenarious assumes that it can own stream's lifetime. The fact that object is disposable is not something that requires to call dispose. Sometimes it just syntax helper. In the case of BinnaryWriter this is the case. (BTW BinnaryWriter is Serializable, lets make serialize it?, how so, how serialize writer?) Regarding hack, I am fail to see one. – Mike Chaliy Jul 05 '09 at 22:22
  • 6
    "The fact that object is disposable is not something that requires to call dispose" - there we again disagree. IDisposable is a contract; unless you have a very good reason, you should dispose it when done. Anything else breaks encapsulation. You shouldn't know or care what it needs disposable for... it is disposable: dispose it. Replied to your other comment (on my post), too. – Marc Gravell Jul 10 '09 at 22:50
  • 2
    Fortunately, `BinaryWriter` does not call `Dispose` in `Finalize` like `FileStream` does. This behavior implies that `BinaryWriter.Dispose` is optional. – Yang Bo Aug 07 '14 at 07:53
9

The protected BinaryWriter.Dispose(bool) method is virtual, and all it does is closes the stream (you can check that it is true in Reflector). -This method is called by the Dispose() method.

You can simply inherit a class from the BinaryWriter and override the Dispose(bool) method to do nothing, or something else alltogether.

Kenan E. K.
  • 13,955
  • 3
  • 43
  • 48