-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Description
When using BinaryWriter.Write(string)
, it attempts to optimize the performance, and when the value is short enough (and the encoding is UTF8), then the operation may bypass the Write7BitEncodedInt
call.
But this is a problem if we use a derived BinaryWriter
where the Write(int)
method is overridden because the Write7BitEncodedInt
method calls the virtual Write(int)
method.
Example: we have a pair of reader-writer that dumps the written/read values while adjusts the current position. Since BinaryReader
always calls the Read7BitEncodedInt
method, the dumped information and offsets slowly drift away when short strings are written:
Reproduction Steps
- Create a derived
BinaryWriter
with an overriddenWrite(int)
method. - Call
Write(string)
with various lengths - Observe that the overridden
Write(int)
is sometimes called, sometimes not, depending on string length.
Expected behavior
BinaryWriter
and BinaryReader
should have a symmetric behavior. When we have a derived BinaryWriter
class, I always expect the overridden Write(int)
method to be called because that's how BinaryReader
also works (ie. its ReadString
always calls ReadInt32
).
Actual behavior
BinaryWriter.Write(string)
sometimes calls the implicit Write(int)
method, sometimes not. See the details above.
Regression?
It works in .NET Framework, and it worked in .NET 5.0.
Known Workarounds
Duplicating the old behavior in a derived class without calling base.Write(string)
(a bit painful).
Configuration
Noticed in .NET 9 Preview 7 but it turns out that we have this behavior since .NET 6.0
Other information
Possible solutions:
- Check in the base constructor if the current type is a derived one, and if so, then initialize the
_useFastUtf8
field tofalse
. - Or, allow only the "semi-optimized" branch, which still calls the
Write7BitEncodedInt
method,