Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/core/compatibility/10.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ If you're migrating an app to .NET 10, the breaking changes listed here might af
|-------|-------------------|--------------------|
| [ActivitySource.CreateActivity and ActivitySource.StartActivity behavior change](core-libraries/10.0/activity-sampling.md) | Behavioral change | Preview 1 |
| [Arm64 SVE nonfaulting loads require mask](core-libraries/10.0/sve-nonfaulting-loads-mask-parameter.md) | Binary/source incompatible | Preview 1 |
| [BufferedStream.WriteByte no longer performs implicit flush](core-libraries/10.0/bufferedstream-writebyte-flush.md) | Behavioral change | Preview 4 |
| [C# 14 overload resolution with span parameters](core-libraries/10.0/csharp-overload-resolution.md) | Behavioral change | Preview 1 |
| [Consistent shift behavior in generic math](core-libraries/10.0/generic-math.md) | Behavioral change | Preview 1 |
| [Default trace context propagator updated to W3C standard](core-libraries/10.0/default-trace-context-propagator.md) | Behavioral change | Preview 4 |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
title: "Breaking change - BufferedStream.WriteByte no longer performs implicit flush"
description: "Learn about the breaking change in .NET 10 where BufferedStream.WriteByte no longer performs an implicit flush when the internal buffer is full."
ms.date: 10/13/2025
ai-usage: ai-assisted
ms.custom: https://github.com/dotnet/docs/issues/496356
dev_langs:
- "csharp"
- "vb"
---

# BufferedStream.WriteByte no longer performs implicit flush

The <xref:System.IO.BufferedStream.WriteByte(System.Byte)?displayProperty=nameWithType> method no longer performs an implicit flush when the internal buffer is full. This change aligns the behavior of `BufferedStream.WriteByte` with other `Write` methods in the <xref:System.IO.BufferedStream> class, such as <xref:System.IO.BufferedStream.Write(System.Byte[],System.Int32,System.Int32)?displayProperty=nameWithType> and <xref:System.IO.BufferedStream.WriteAsync(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken)?displayProperty=nameWithType>, which don't perform an implicit flush.

## Version introduced

.NET 10 Preview 4

## Previous behavior

Previously, when the internal buffer of a `BufferedStream` was full, calling `WriteByte` automatically flushed the buffer to the underlying stream. This behavior was inconsistent with other `Write` methods in `BufferedStream`.

The following example demonstrates the previous behavior:

:::code language="csharp" source="./snippets/bufferedstream-writebyte-flush/csharp/Program.cs" id="PreviousBehavior":::
:::code language="vb" source="./snippets/bufferedstream-writebyte-flush/vb/Program.vb" id="PreviousBehavior":::

## New behavior

Starting in .NET 10, the `WriteByte` method no longer performs an implicit flush when the internal buffer is full. The buffer is only flushed when the <xref:System.IO.BufferedStream.Flush?displayProperty=nameWithType> method is explicitly called or when the `BufferedStream` is disposed.

## Type of breaking change

This change is a [behavioral change](../../categories.md#behavioral-change).

## Reason for change

The implicit flush behavior of <xref:System.IO.BufferedStream.WriteByte(System.Byte)?displayProperty=nameWithType> 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`, update your code to explicitly call the `Flush` method when needed. For example:

**Before:**

:::code language="csharp" source="./snippets/bufferedstream-writebyte-flush/csharp/Program.cs" id="Before":::
:::code language="vb" source="./snippets/bufferedstream-writebyte-flush/vb/Program.vb" id="Before":::

**After:**

:::code language="csharp" source="./snippets/bufferedstream-writebyte-flush/csharp/Program.cs" id="After":::
:::code language="vb" source="./snippets/bufferedstream-writebyte-flush/vb/Program.vb" id="After":::

## Affected APIs

- <xref:System.IO.BufferedStream.WriteByte(System.Byte)?displayProperty=fullName>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System;
using System.IO;

// <PreviousBehavior>
StreamWithFlush streamWithFlush = new();
BufferedStream bufferedStream = new(streamWithFlush, bufferSize: 4);

// Write 4 bytes to fill the buffer
bufferedStream.WriteByte(1);
bufferedStream.WriteByte(2);
bufferedStream.WriteByte(3);
bufferedStream.WriteByte(4); // In .NET 9 and earlier, this caused an implicit flush

class StreamWithFlush : MemoryStream
{
public override void Flush()
{
Console.WriteLine("Flush was called.");

base.Flush();
}
}
// </PreviousBehavior>

class BeforeExample
{
static void Example()
{
// <Before>
BufferedStream bufferedStream = new(new MemoryStream(), bufferSize: 4);
bufferedStream.WriteByte(1);
bufferedStream.WriteByte(2);
bufferedStream.WriteByte(3);
bufferedStream.WriteByte(4); // Implicit flush occurred here in .NET 9 and earlier
// </Before>
}
}

class AfterExample
{
static void Example()
{
// <After>
BufferedStream bufferedStream = new(new MemoryStream(), bufferSize: 4);
bufferedStream.WriteByte(1);
bufferedStream.WriteByte(2);
bufferedStream.WriteByte(3);
bufferedStream.WriteByte(4);
bufferedStream.Flush(); // Explicit flush
// </After>
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<RootNamespace>BufferedStreamWriteByteFlush</RootNamespace>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
Imports System
Imports System.IO

Module Program
Sub Main()
' Main entry point
End Sub
End Module

' <PreviousBehavior>
Module PreviousBehaviorExample
Sub Example()
Dim streamWithFlush As New StreamWithFlush()
Dim bufferedStream As New BufferedStream(streamWithFlush, bufferSize:=4)

' Write 4 bytes to fill the buffer
bufferedStream.WriteByte(1)
bufferedStream.WriteByte(2)
bufferedStream.WriteByte(3)
bufferedStream.WriteByte(4) ' In .NET 9 and earlier, this caused an implicit flush
End Sub

Class StreamWithFlush
Inherits MemoryStream

Public Overrides Sub Flush()
Console.WriteLine("Flush was called.")
MyBase.Flush()
End Sub
End Class
End Module
' </PreviousBehavior>

Module BeforeExample
Sub Example()
' <Before>
Dim bufferedStream As New BufferedStream(New MemoryStream(), bufferSize:=4)
bufferedStream.WriteByte(1)
bufferedStream.WriteByte(2)
bufferedStream.WriteByte(3)
bufferedStream.WriteByte(4) ' Implicit flush occurred here in .NET 9 and earlier
' </Before>
End Sub
End Module

Module AfterExample
Sub Example()
' <After>
Dim bufferedStream As New BufferedStream(New MemoryStream(), bufferSize:=4)
bufferedStream.WriteByte(1)
bufferedStream.WriteByte(2)
bufferedStream.WriteByte(3)
bufferedStream.WriteByte(4)
bufferedStream.Flush() ' Explicit flush
' </After>
End Sub
End Module

2 changes: 2 additions & 0 deletions docs/core/compatibility/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ items:
href: core-libraries/10.0/activity-sampling.md
- name: Arm64 SVE nonfaulting loads require mask
href: core-libraries/10.0/sve-nonfaulting-loads-mask-parameter.md
- name: BufferedStream.WriteByte no longer performs implicit flush
href: core-libraries/10.0/bufferedstream-writebyte-flush.md
- name: C# 14 overload resolution with span parameters
href: core-libraries/10.0/csharp-overload-resolution.md
- name: Consistent shift behavior in generic math
Expand Down
Loading