Skip to content

[Breaking change]: Remove implicit flush from BufferedStream.WriteByte #49418

@jeffhandley

Description

@jeffhandley

Description

Starting in .NET 10 Preview 4, the BufferedStream.WriteByte method no longer performs an implicit flush when the internal buffer is full. This change was made to align the behavior of BufferedStream.WriteByte with other Write methods in the BufferedStream class, such as Write and WriteAsync, which do not perform an implicit flush.

Previously, when the internal buffer of a BufferedStream was full, calling WriteByte would automatically flush the buffer to the underlying stream. This behavior was inconsistent with other Write methods in BufferedStream, which do not perform an implicit flush under similar circumstances. The change ensures consistent behavior across all Write methods in BufferedStream.

This change addresses an issue where the implicit flush could lead to unexpected performance degradation or unintended side effects when working with streams that are sensitive to flush operations.

For more details, see the original pull request and the related GitHub issue.

Version

.NET 10 Preview 4

Previous behavior

When the internal buffer of a BufferedStream was full, calling WriteByte would automatically flush the buffer to the underlying stream. This behavior was inconsistent with other Write methods in BufferedStream.

Example

using System;
using System.IO;

var memoryStream = new MemoryStream();
var bufferedStream = new BufferedStream(memoryStream, bufferSize: 4);

// Write 4 bytes to fill the buffer
bufferedStream.WriteByte(1);
bufferedStream.WriteByte(2);
bufferedStream.WriteByte(3);
bufferedStream.WriteByte(4);

// Write one more byte, which causes an implicit flush
bufferedStream.WriteByte(5);

// The underlying stream now contains the first 4 bytes
Console.WriteLine(memoryStream.Length); // Output: 4

New behavior

The WriteByte method no longer performs an implicit flush when the internal buffer is full. Instead, the buffer will remain full until an explicit flush is performed or the buffer is overwritten by subsequent writes.

Example

using System;
using System.IO;

var memoryStream = new MemoryStream();
var bufferedStream = new BufferedStream(memoryStream, bufferSize: 4);

// Write 4 bytes to fill the buffer
bufferedStream.WriteByte(1);
bufferedStream.WriteByte(2);
bufferedStream.WriteByte(3);
bufferedStream.WriteByte(4);

// Write one more byte; no implicit flush occurs
bufferedStream.WriteByte(5);

// The underlying stream remains empty until an explicit flush
Console.WriteLine(memoryStream.Length); // Output: 0

// Perform an explicit flush
bufferedStream.Flush();

// The underlying stream now contains all 5 bytes
Console.WriteLine(memoryStream.Length); // Output: 5

Type of breaking change

  • Behavioral change: Existing binaries might behave differently at runtime.

Reason for change

The implicit flush behavior of BufferedStream.WriteByte was inconsistent with other Write methods in the BufferedStream class, such as Write and WriteAsync. This inconsistency could lead to unexpected performance issues or unintended side effects when working with streams that are sensitive to flush operations. Removing the implicit flush ensures consistent behavior across all Write methods in BufferedStream.

Recommended action

If your application relies on the implicit flush behavior of BufferedStream.WriteByte, you should update your code to explicitly call the Flush method when needed. For example:

Before

bufferedStream.WriteByte(1);
bufferedStream.WriteByte(2);
bufferedStream.WriteByte(3);
bufferedStream.WriteByte(4);
bufferedStream.WriteByte(5); // Implicit flush occurs here

After

bufferedStream.WriteByte(1);
bufferedStream.WriteByte(2);
bufferedStream.WriteByte(3);
bufferedStream.WriteByte(4);
bufferedStream.WriteByte(5);
bufferedStream.Flush(); // Explicit flush

Affected APIs

  • System.IO.BufferedStream.WriteByte

Additional information

This change was introduced in .NET 10 Preview 4. For more details, see the pull request and the related issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions