Is this not plain wrong, BinaryFormatter

  • Thread starter Alexander Muylaert
  • Start date
A

Alexander Muylaert

Hi

for some reason the BinaryWriter is Closing the stream when disposed. I
don't want it to close the stream. According to my logic the BinaryWriter
should Write to the stream, nothing more. If I want the stream to close, I
will close it myself, not some helper class.

According to me the BinaryWriter should *not* touch the stream. Except for
the expected behaviour of incrementing the Position of the stream and
writing data to it.

Imagine this ...

private void WriteWhateverBinaryThingsToStream(Stream aStream){
using (BinaryWriter Writer = New BinaryWriter(aStream)){
Writer.WriteInt64(MyInt64);
Writer.WriteString(MyString);
}
}

public void SaveToFile(string FileName){
using (FileStream fs = new FileStream("c:\\test.dat", FileMode.Create))
{
WriteWhateverBinaryThingsToStream(fs);
WriteWhateverBinaryThingsToStream(fs); // stream is already close
here.
WriteWhateverBinaryThingsToStream(fs);
}
}

Even when I don't use the "using" keyword I cannot create multiple instances
of BinaryWriters that work on the same stream. Because GC can close the
stream at any time. Please tell me I'm doing something very, very wrong
here. If my assumption is correct, could somebody explain the advantages to
me. I see none :(.


Kind regards and many thanks

Alexander
 
J

Jon Skeet [C# MVP]

Alexander Muylaert said:
for some reason the BinaryWriter is Closing the stream when disposed. I
don't want it to close the stream. According to my logic the BinaryWriter
should Write to the stream, nothing more. If I want the stream to close, I
will close it myself, not some helper class.

I believe the idea is it wraps the stream entirely. In my view there
should be an optional parameter to the constructor saying whether or
not the BinaryWriter effectively "owns" the stream - in some cases you
want to be able to just pass a stream reference off to the constructor
and know that it will be taken care of; in other cases you want the
behaviour you've described below.
 
A

Alexander Muylaert

So...

Two possible fixes for me.

* I write my own BinaryWriter. (with normal behaviour)
* I pass the writer as a Parameter

Both sollutions suck. The first gives me a ton of extra work. The second
is even worse, by passing the writer as a parameter, I need to use the
writer to stream something. Wich perhaps I don't want, or I should access
the BaseStream property. But ...

Hmmm

Who's idea was this and what was (s)he thinking...

Rule n°1: Free whatever you create (even with GC this one applies, I adore
the "using" statement)
Rule n°2: Don't free something that you didn't create.
Rule n°3: First create the object, next Implement the dispose, third
implement the thing inbetween.

Even when you have no GC the above to rules will prevent all leaks and null
pointer exceptions. One should only apply these three very simple rules,
extremely strictly. No buts... :)

Imho this has nothing to do with GC, closing the stream is just a bad idea
and makes the binarywriter less interesting for me. Especially in the
situation I mentioned. And trust me, this happens a lot.

Kind regards

Alexander
 
D

Daniel O'Connell [C# MVP]

Alexander Muylaert said:
Hi

for some reason the BinaryWriter is Closing the stream when disposed. I
don't want it to close the stream. According to my logic the BinaryWriter
should Write to the stream, nothing more. If I want the stream to close,
I
will close it myself, not some helper class.

According to me the BinaryWriter should *not* touch the stream. Except
for
the expected behaviour of incrementing the Position of the stream and
writing data to it.

Imagine this ...

private void WriteWhateverBinaryThingsToStream(Stream aStream){
using (BinaryWriter Writer = New BinaryWriter(aStream)){
Writer.WriteInt64(MyInt64);
Writer.WriteString(MyString);
}
}

public void SaveToFile(string FileName){
using (FileStream fs = new FileStream("c:\\test.dat", FileMode.Create))
{
WriteWhateverBinaryThingsToStream(fs);
WriteWhateverBinaryThingsToStream(fs); // stream is already
close
here.
WriteWhateverBinaryThingsToStream(fs);
}
}

Even when I don't use the "using" keyword I cannot create multiple
instances
of BinaryWriters that work on the same stream. Because GC can close the
stream at any time. Please tell me I'm doing something very, very wrong
here. If my assumption is correct, could somebody explain the advantages
to
me. I see none :(.

Its one of the frustrations inherent to trying to please everyone. Sometimes
you want a reader to be just a visitor, something that does something and
goes away, othertimes the reader creates the stream, and othertimes still
you give the reader complete control over the stream and let it do the work
instead of you. Its terribly difficult to determine which path is the
correct one for a library, really. The designers chose to follow the
annoying, albeit more common, path of designing readers and writers to
control the stream. However, I think I'd be equally annoyed with the other
option of having to close both the stream and the reader seperatly.
Frankly I'd like to see versions of some readers that don't control the
stream, but I'm not holding my breath(perhaps implemented statically, in a
way similar to Directory and DirectoryInfo, etc). The easiest path you'll
find to get aroudn this is to create a stream that ignores close and wraps
other streams(if you look around, there is bound to be plenty of examples of
this on gotdotnet, codeproject, etc)
 
D

Daniel O'Connell [C# MVP]

Rule n°2: Don't free something that you didn't create.

I'll agree with that with the exception of a wrapper. Wrap-and-forget
semantics are very valuable sometimes, though they create annoyances when
they aren't.
 
D

Daniel O'Connell [C# MVP]

Alexander Muylaert said:
I agree with your point of view. But why, my God why...

Think about it, 90% of the time you wrap a stream with *one* reader\writer
,do what you have to do, and move on. In that case one close operation makes
sense. Also, it boosts flexibilty. Some readers and writers are highly
position sensitive and will probably collapse if you change the
stream(XmlTextReader comes to mind). You *cannot* double wrap these readers
without risking some really bad mojo. The reader could have been implemented
to work with multiple stream accessors it but that throws *alot* of
threading work into the reader, massiving increasing complexity. By implying
wrap and forget semantics 90% of the use case is covered and the expected
behaviour removes a large portion of the probable mistakes that are going to
be made with readers combined with strings, the downside is 10% of hte use
case is out of luck.
 
D

Daniel O'Connell [C# MVP]

Daniel O'Connell said:
Think about it, 90% of the time you wrap a stream with *one* reader\writer
,do what you have to do, and move on. In that case one close operation
makes sense. Also, it boosts flexibilty. Some readers and writers are
highly position sensitive and will probably collapse if you change the
stream(XmlTextReader comes to mind). You *cannot* double wrap these
readers without risking some really bad mojo. The reader could have been
implemented to work with multiple stream accessors it but that throws
*alot* of threading work into the reader, massiving increasing complexity.
By implying

err, that should have been "massivly increasing testing complexity", not the
somewhat mixed thing I wrote.
 
N

Nicholas Paldino [.NET/C# MVP]

Alexander,

I don't know if this will be the best solution for you, but you could
serialize your object to a MemoryStream, and then write the bytes that are
contained in the stream to whatever stream you want to keep open.

Of course, this could be prohibitive, depending on the size of your
objects.

Hope this helps.
 
S

Sherif ElMetainy

Hello

Do not Close the BinaryWriter (i.e. do not use using keyword). The only
thing that the Close method (Dispose method when using using keyword) is
close the BaseStream. The BinaryWriter doesn't hold any other resources.
And since BinaryWriter doesn't override the Finalize method so the
BaseStream will not be closed when the BinaryWriter is garbage collected.

I hope this helps
Best regards,
Sherif
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top