Skip to content

Commit b5b96be

Browse files
authored
Merge pull request #49136 from dotnet/main
Merge main into live
2 parents 931a5dc + e4d5897 commit b5b96be

File tree

31 files changed

+711
-27
lines changed

31 files changed

+711
-27
lines changed

docs/core/compatibility/10.0.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ If you're migrating an app to .NET 10, the breaking changes listed here might af
4141
|-------|-------------------|--------------------|
4242
| [ActivitySource.CreateActivity and ActivitySource.StartActivity behavior change](core-libraries/10.0/activity-sampling.md) | Behavioral change | Preview 1 |
4343
| [Arm64 SVE nonfaulting loads require mask](core-libraries/10.0/sve-nonfaulting-loads-mask-parameter.md) | Binary/source incompatible | Preview 1 |
44+
| [BufferedStream.WriteByte no longer performs implicit flush](core-libraries/10.0/bufferedstream-writebyte-flush.md) | Behavioral change | Preview 4 |
4445
| [C# 14 overload resolution with span parameters](core-libraries/10.0/csharp-overload-resolution.md) | Behavioral change | Preview 1 |
4546
| [Consistent shift behavior in generic math](core-libraries/10.0/generic-math.md) | Behavioral change | Preview 1 |
4647
| [Default trace context propagator updated to W3C standard](core-libraries/10.0/default-trace-context-propagator.md) | Behavioral change | Preview 4 |
@@ -75,6 +76,7 @@ If you're migrating an app to .NET 10, the breaking changes listed here might af
7576

7677
| Title | Type of change | Introduced version |
7778
|-------|---------------------|--------------------|
79+
| [BackgroundService runs all of ExecuteAsync as a Task](extensions/10.0/backgroundservice-executeasync-task.md) | Behavioral change | Preview 1 |
7880
| [Null values preserved in configuration](extensions/10.0/configuration-null-values-preserved.md) | Behavioral change | Preview 7 |
7981
| [Message no longer duplicated in Console log output](extensions/10.0/console-json-logging-duplicate-messages.md) | Behavioral change | Preview 7 |
8082
| [ProviderAliasAttribute moved to Microsoft.Extensions.Logging.Abstractions assembly](extensions/10.0/provideraliasattribute-moved-assembly.md) | Source incompatible | Preview 4 |
@@ -109,6 +111,7 @@ If you're migrating an app to .NET 10, the breaking changes listed here might af
109111
| [`dotnet` CLI commands log non-command-relevant data to stderr](sdk/10.0/dotnet-cli-stderr-output.md) | Behavioral change | RC 2 |
110112
| [.NET tool packaging creates RuntimeIdentifier-specific tool packages](sdk/10.0/dotnet-tool-pack-publish.md) | Behavioral change | Preview 6 |
111113
| [Default workload configuration from 'loose manifests' to 'workload sets' mode](sdk/10.0/default-workload-config.md) | Behavioral change | Preview 2 |
114+
| [dnx.ps1 file is no longer included in .NET SDK](sdk/10.0/dnx-ps1-removed.md) | Source incompatible | GA |
112115
| [`dotnet new sln` defaults to SLNX file format](sdk/10.0/dotnet-new-sln-slnx-default.md) | Behavioral change | RC 1 |
113116
| [`dotnet package list` performs restore](sdk/10.0/dotnet-package-list-restore.md) | Behavioral change | Preview 4 |
114117
| [`dotnet restore` audits transitive packages](sdk/10.0/nugetaudit-transitive-packages.md) | Behavioral change | Preview 3 |
@@ -122,6 +125,7 @@ If you're migrating an app to .NET 10, the breaking changes listed here might af
122125
| [NuGet packages with no runtime assets aren't included in deps.json](sdk/10.0/deps-json-trimmed-packages.md) | Source incompatible | Preview 5 |
123126
| [PackageReference without a version raises an error](sdk/10.0/nu1015-packagereference-version.md) | Behavioral change | Preview 6 |
124127
| [PrunePackageReference privatizes direct prunable references](sdk/10.0/prune-packagereference-privateassets.md) | Behavioral change | Preview 7 |
128+
| [Version requirements for .NET 10 SDK](sdk/10.0/version-requirements.md) | Behavioral change | RC 2 |
125129
| [HTTP warnings promoted to errors in `dotnet package list` and `dotnet package search`](sdk/10.0/http-warnings-to-errors.md) | Behavioral/source incompatible change | Preview 4 |
126130
| [NUGET_ENABLE_ENHANCED_HTTP_RETRY environment variable removed](sdk/10.0/nuget-enhanced-http-retry-removed.md) | Behavioral change | Preview 6 |
127131
| [NuGet logs an error for invalid package IDs](sdk/10.0/nuget-packageid-validation.md) | Behavioral change | RC 1 |

docs/core/compatibility/8.0.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ If you're migrating an app to .NET 8, the breaking changes listed here might aff
5656
| [GetFolderPath behavior on Unix](core-libraries/8.0/getfolderpath-unix.md) | Behavioral change |
5757
| [GetSystemVersion no longer returns ImageRuntimeVersion](core-libraries/8.0/getsystemversion.md) | Behavioral change |
5858
| [ITypeDescriptorContext nullable annotations](core-libraries/8.0/itypedescriptorcontext-props.md) | Source incompatible |
59+
| [LDAP APIs not available on .NET Standard / .NET Framework](core-libraries/8.0/ldap-netstandard-apis.md) | Binary incompatible |
5960
| [Legacy Console.ReadKey removed](core-libraries/8.0/console-readkey-legacy.md) | Behavioral change |
6061
| [Method builders generate parameters with HasDefaultValue set to false](core-libraries/8.0/parameterinfo-hasdefaultvalue.md) | Behavioral change |
6162
| [Package part URIs are now compared case-insensitively in System.IO.Packaging](core-libraries/8.0/system-io-packaging-case-insensitive-uri.md) | Behavioral change |
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
---
2+
title: "Breaking change - BufferedStream.WriteByte no longer performs implicit flush"
3+
description: "Learn about the breaking change in .NET 10 where BufferedStream.WriteByte no longer performs an implicit flush when the internal buffer is full."
4+
ms.date: 10/13/2025
5+
ai-usage: ai-assisted
6+
ms.custom: https://github.com/dotnet/docs/issues/496356
7+
dev_langs:
8+
- "csharp"
9+
- "vb"
10+
---
11+
12+
# BufferedStream.WriteByte no longer performs implicit flush
13+
14+
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.
15+
16+
## Version introduced
17+
18+
.NET 10 Preview 4
19+
20+
## Previous behavior
21+
22+
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`.
23+
24+
The following example demonstrates the previous behavior:
25+
26+
:::code language="csharp" source="./snippets/bufferedstream-writebyte-flush/csharp/Program.cs" id="PreviousBehavior":::
27+
:::code language="vb" source="./snippets/bufferedstream-writebyte-flush/vb/Program.vb" id="PreviousBehavior":::
28+
29+
## New behavior
30+
31+
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.
32+
33+
## Type of breaking change
34+
35+
This change is a [behavioral change](../../categories.md#behavioral-change).
36+
37+
## Reason for change
38+
39+
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`.
40+
41+
## Recommended action
42+
43+
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:
44+
45+
**Before:**
46+
47+
:::code language="csharp" source="./snippets/bufferedstream-writebyte-flush/csharp/Program.cs" id="Before":::
48+
:::code language="vb" source="./snippets/bufferedstream-writebyte-flush/vb/Program.vb" id="Before":::
49+
50+
**After:**
51+
52+
:::code language="csharp" source="./snippets/bufferedstream-writebyte-flush/csharp/Program.cs" id="After":::
53+
:::code language="vb" source="./snippets/bufferedstream-writebyte-flush/vb/Program.vb" id="After":::
54+
55+
## Affected APIs
56+
57+
- <xref:System.IO.BufferedStream.WriteByte(System.Byte)?displayProperty=fullName>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net10.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
</Project>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using System;
2+
using System.IO;
3+
4+
// <PreviousBehavior>
5+
StreamWithFlush streamWithFlush = new();
6+
BufferedStream bufferedStream = new(streamWithFlush, bufferSize: 4);
7+
8+
// Write 4 bytes to fill the buffer
9+
bufferedStream.WriteByte(1);
10+
bufferedStream.WriteByte(2);
11+
bufferedStream.WriteByte(3);
12+
bufferedStream.WriteByte(4); // In .NET 9 and earlier, this caused an implicit flush
13+
14+
class StreamWithFlush : MemoryStream
15+
{
16+
public override void Flush()
17+
{
18+
Console.WriteLine("Flush was called.");
19+
20+
base.Flush();
21+
}
22+
}
23+
// </PreviousBehavior>
24+
25+
class BeforeExample
26+
{
27+
static void Example()
28+
{
29+
// <Before>
30+
BufferedStream bufferedStream = new(new MemoryStream(), bufferSize: 4);
31+
bufferedStream.WriteByte(1);
32+
bufferedStream.WriteByte(2);
33+
bufferedStream.WriteByte(3);
34+
bufferedStream.WriteByte(4); // Implicit flush occurred here in .NET 9 and earlier
35+
// </Before>
36+
}
37+
}
38+
39+
class AfterExample
40+
{
41+
static void Example()
42+
{
43+
// <After>
44+
BufferedStream bufferedStream = new(new MemoryStream(), bufferSize: 4);
45+
bufferedStream.WriteByte(1);
46+
bufferedStream.WriteByte(2);
47+
bufferedStream.WriteByte(3);
48+
bufferedStream.WriteByte(4);
49+
bufferedStream.Flush(); // Explicit flush
50+
// </After>
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<RootNamespace>BufferedStreamWriteByteFlush</RootNamespace>
6+
<TargetFramework>net10.0</TargetFramework>
7+
</PropertyGroup>
8+
9+
</Project>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
Imports System
2+
Imports System.IO
3+
4+
Module Program
5+
Sub Main()
6+
' Main entry point
7+
End Sub
8+
End Module
9+
10+
' <PreviousBehavior>
11+
Module PreviousBehaviorExample
12+
Sub Example()
13+
Dim streamWithFlush As New StreamWithFlush()
14+
Dim bufferedStream As New BufferedStream(streamWithFlush, bufferSize:=4)
15+
16+
' Write 4 bytes to fill the buffer
17+
bufferedStream.WriteByte(1)
18+
bufferedStream.WriteByte(2)
19+
bufferedStream.WriteByte(3)
20+
bufferedStream.WriteByte(4) ' In .NET 9 and earlier, this caused an implicit flush
21+
End Sub
22+
23+
Class StreamWithFlush
24+
Inherits MemoryStream
25+
26+
Public Overrides Sub Flush()
27+
Console.WriteLine("Flush was called.")
28+
MyBase.Flush()
29+
End Sub
30+
End Class
31+
End Module
32+
' </PreviousBehavior>
33+
34+
Module BeforeExample
35+
Sub Example()
36+
' <Before>
37+
Dim bufferedStream As New BufferedStream(New MemoryStream(), bufferSize:=4)
38+
bufferedStream.WriteByte(1)
39+
bufferedStream.WriteByte(2)
40+
bufferedStream.WriteByte(3)
41+
bufferedStream.WriteByte(4) ' Implicit flush occurred here in .NET 9 and earlier
42+
' </Before>
43+
End Sub
44+
End Module
45+
46+
Module AfterExample
47+
Sub Example()
48+
' <After>
49+
Dim bufferedStream As New BufferedStream(New MemoryStream(), bufferSize:=4)
50+
bufferedStream.WriteByte(1)
51+
bufferedStream.WriteByte(2)
52+
bufferedStream.WriteByte(3)
53+
bufferedStream.WriteByte(4)
54+
bufferedStream.Flush() ' Explicit flush
55+
' </After>
56+
End Sub
57+
End Module
58+
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
title: "Breaking change: TrustedCertificatesDirectory and StartNewTlsSessionContext are not available on .NET Standard / .NET Framework"
3+
description: Learn about the .NET 8 breaking change in core .NET libraries where TrustedCertificatesDirectory and StartNewTlsSessionContext are not available when targeting .NET Standard 2.0.
4+
ms.date: 10/14/2025
5+
ai-usage: ai-assisted
6+
ms.custom: https://github.com/dotnet/docs/issues/48879
7+
---
8+
# TrustedCertificatesDirectory and StartNewTlsSessionContext are not available on .NET Standard / .NET Framework
9+
10+
The following APIs were accidentally exposed in the `netstandard2.0` version of the System.DirectoryServices.Protocols NuGet package version 8.0.1:
11+
12+
- <xref:System.DirectoryServices.Protocols.LdapSessionOptions.TrustedCertificatesDirectory?displayProperty=nameWithType>
13+
- <xref:System.DirectoryServices.Protocols.LdapSessionOptions.StartNewTlsSessionContext?displayProperty=nameWithType>
14+
15+
These APIs aren't implemented on .NET Framework and weren't intended to be exposed when targeting `netstandard2.0`. Starting with version 8.0.2 of the System.DirectoryServices.Protocols NuGet package, these APIs are unavailable when targeting `netstandard2.0`.
16+
17+
## Previous behavior
18+
19+
In System.DirectoryServices.Protocols NuGet package version 8.0.1, the <xref:System.DirectoryServices.Protocols.LdapSessionOptions.TrustedCertificatesDirectory?displayProperty=nameWithType> property and <xref:System.DirectoryServices.Protocols.LdapSessionOptions.StartNewTlsSessionContext?displayProperty=nameWithType> method could be used from a `netstandard2.0` library.
20+
21+
## New behavior
22+
23+
Starting with System.DirectoryServices.Protocols NuGet package version 8.0.2, attempting to use these APIs from a `netstandard2.0` library results in a compilation error.
24+
25+
## Version introduced
26+
27+
System.DirectoryServices.Protocols NuGet package version 8.0.2
28+
29+
## Type of breaking change
30+
31+
This change can affect [binary compatibility](../../categories.md#binary-compatibility).
32+
33+
## Reason for change
34+
35+
The APIs didn't work on all compatible frameworks.
36+
37+
## Recommended action
38+
39+
If you need to use these APIs, target .NET instead of `netstandard2.0`.
40+
41+
## Affected APIs
42+
43+
- <xref:System.DirectoryServices.Protocols.LdapSessionOptions.TrustedCertificatesDirectory?displayProperty=fullName>
44+
- <xref:System.DirectoryServices.Protocols.LdapSessionOptions.StartNewTlsSessionContext?displayProperty=fullName>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
title: "Breaking change: BackgroundService runs all of ExecuteAsync as a Task"
3+
description: "Learn about the breaking change in .NET 10 where BackgroundService now runs the entirety of ExecuteAsync on a background thread instead of running the synchronous portion on the main thread."
4+
ms.date: 10/13/2025
5+
ai-usage: ai-assisted
6+
ms.custom: https://github.com/dotnet/runtime/issues/116181
7+
---
8+
9+
# BackgroundService runs all of ExecuteAsync as a Task
10+
11+
<xref:Microsoft.Extensions.Hosting.BackgroundService> now runs the entirety of <xref:Microsoft.Extensions.Hosting.BackgroundService.ExecuteAsync%2A> on a background thread. Previously, the synchronous portion of `ExecuteAsync` (before the first `await`) ran on the main thread during service startup, blocking other services from starting. Only code after the first `await` ran on a background thread.
12+
13+
## Version introduced
14+
15+
.NET 10
16+
17+
## Previous behavior
18+
19+
Previously, the synchronous portion of `ExecuteAsync` ran on the main thread and blocked other services from starting.
20+
21+
## New behavior
22+
23+
Starting in .NET 10, all of `ExecuteAsync` runs on a background thread, and no part of it blocks other services from starting.
24+
25+
## Type of breaking change
26+
27+
This change is a [behavioral change](../../categories.md#behavioral-change).
28+
29+
## Reason for change
30+
31+
The previous behavior was a common pitfall that didn't meet user expectations. Most implementers of `BackgroundService` didn't understand that the synchronous portion before the first `await` blocked other services from starting during application startup.
32+
33+
## Recommended action
34+
35+
If you require any part of your `BackgroundService.ExecuteAsync` to run earlier during startup (synchronously and blocking other services), you can do any one of the following:
36+
37+
- Place the code that needs to run synchronously in the constructor, and it executes as part of the service construction.
38+
- Override `StartAsync` and do some work before calling `base.StartAsync`. `StartAsync` retains the behavior that its synchronous portion runs synchronously during startup and blocks other services from starting.
39+
- If you want to run code at a more specific time during service startup, implement <xref:Microsoft.Extensions.Hosting.IHostedLifecycleService?displayProperty=fullName> on your `BackgroundService`.
40+
- Forgo `BackgroundService` entirely and implement your own <xref:Microsoft.Extensions.Hosting.IHostedService?displayProperty=fullName>.
41+
42+
## Affected APIs
43+
44+
- <xref:Microsoft.Extensions.Hosting.BackgroundService.ExecuteAsync%2A?displayProperty=fullName>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
title: "Breaking change - dnx.ps1 file is no longer included in .NET SDK"
3+
description: "Learn about the breaking change in .NET 10 where the dnx.ps1 script is no longer included in Windows versions of the .NET SDK."
4+
ms.date: 10/13/2025
5+
ai-usage: ai-assisted
6+
ms.custom: https://github.com/dotnet/docs/issues/497988
7+
---
8+
9+
# dnx.ps1 file is no longer included in .NET SDK
10+
11+
The `dnx.ps1` shim script is no longer included in the .NET SDK.
12+
13+
## Version introduced
14+
15+
.NET 10 GA
16+
17+
## Previous behavior
18+
19+
Since .NET 10 Preview 7, on Windows versions of the .NET SDK, a `dnx.ps1` script was included in the dotnet root folder, alongside `dotnet.exe` and `dnx.cmd`.
20+
21+
## New behavior
22+
23+
The `dnx.ps1` script is no longer included. The `dnx.cmd` script remains available for executing tools.
24+
25+
## Type of breaking change
26+
27+
This change can affect <a>source compatibility</a>.
28+
29+
## Reason for change
30+
31+
The `dnx.ps1` script was added to avoid an extra `Terminate Batch Job` prompt when cancelling tools run via `dnx` with <kbd>Ctrl+C</kbd>. However, PowerShell has special handling for `--`, so if `--` was passed on the command line, it never made it through to `dnx`. This meant that in PowerShell, it was impossible to pass options to a tool using `dnx` if `dnx` itself has the same option. For example, `dnx dotnet-serve -- --help` showed the help for `dnx` instead of the help for `dotnet-serve`.
32+
33+
## Recommended action
34+
35+
In most cases, the `dnx.cmd` script is used instead so no action is necessary. If you were calling `dnx.ps1` directly, switch to `dnx.cmd`.
36+
37+
## Affected APIs
38+
39+
None.

0 commit comments

Comments
 (0)