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
42 changes: 21 additions & 21 deletions docs/azure/includes/dotnet-all.md

Large diffs are not rendered by default.

26 changes: 13 additions & 13 deletions docs/azure/includes/dotnet-new.md

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions docs/core/compatibility/11.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ See [Breaking changes in ASP.NET Core 11](/aspnet/core/breaking-changes/11/overv
| [DeflateStream and GZipStream write headers and footers for empty payload](core-libraries/11/deflatestream-gzipstream-empty-payload.md) | Behavioral change |
| [Environment.GetCommandLineArgs()[0] preserves the apphost invocation name](core-libraries/11/environment-getcommandlineargs-apphost-invocation-name.md) | Behavioral change |
| [Environment.TickCount made consistent with Windows timeout behavior](core-libraries/11/environment-tickcount-windows-behavior.md) | Behavioral change |
| [Generated WMI collection and enumerator wrappers implement IDisposable](core-libraries/11/wmi-wrappers-implement-idisposable.md) | Source/behavioral change |
| [Math.Round and MathF.Round return correctly rounded results](core-libraries/11/math-round-digits.md) | Behavioral change |
| [Named mutexes default to user scope on Unix](core-libraries/11/named-mutexes-unix-default-scope.md) | Behavioral change |
| [NamedPipeServerStream with PipeOptions.CurrentUserOnly tightens Unix socket file permissions](core-libraries/11/namedpipeserverstream-unix-permissions.md) | Behavioral change |
Expand Down Expand Up @@ -72,6 +73,7 @@ See [Breaking changes in EF Core 11](/ef/core/what-is-new/ef-core-11.0/breaking-
|-------|-------------------|
| [ChangeToken.OnChange async overloads rebind existing Task-returning callbacks](extensions/11/changetoken-onchange-async-overloads-rebind-callbacks.md) | Behavioral change |
| [Dependency injection scope disposal aggregates exceptions](extensions/11/dependency-injection-disposal-exceptions.md) | Behavioral change |
| [Empty strings in chained configuration override earlier providers](extensions/11/chained-configuration-empty-string.md) | Behavioral change |
| [FileConfigurationProvider doesn't raise reload token after ignored load failure](extensions/11/fileconfigurationprovider-reload-token-load-failure.md) | Behavioral change |
| [FileConfigurationSource.OnLoadException callback is called for IO errors](extensions/11/fileconfigurationsource-onloadexception-io-errors.md) | Behavioral change |
| [IHost.RunAsync and IHost.StopAsync throw when a BackgroundService fails](extensions/11/ihost-runasync-stopasync-throw-backgroundservice-failure.md) | Behavioral change |
Expand Down Expand Up @@ -128,6 +130,7 @@ See [Breaking changes in EF Core 11](/ef/core/what-is-new/ef-core-11.0/breaking-
| Title | Type of change |
|-------------------------------------------------------------------|-------------------|
| [dnx scripts bypass global.json SDK selection](sdk/11/dnx-scripts-bypass-global-json.md) | Behavioral change |
| [Full build skipped for Native AOT publish](sdk/11/aot-publish-skips-full-build.md) | Behavioral change |
| [mono launch target not set for .NET Framework apps](sdk/11/mono-launch-target-removed.md) | Behavioral change |
| [NativeAOT CLI command handling enabled by default](sdk/11/native-cli-command-handling-enabled.md) | Behavioral change |
| [NU1703 warns for packages that use deprecated MonoAndroid framework assets](sdk/11/nu1703-deprecated-monoandroid-framework.md) | Source incompatible |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
title: "Breaking change: Generated WMI wrappers implement IDisposable"
description: "Learn about the breaking change in .NET 11 where generated strongly typed WMI collection and enumerator wrappers implement IDisposable."
ms.date: 10/27/2026
ai-usage: ai-assisted
---

# Generated WMI wrappers implement IDisposable

Starting in .NET 11, strongly typed WMI collection wrappers and their enumerators generated by `ManagementClass.GetStronglyTypedClassCode` implement <xref:System.IDisposable>. Calling `Dispose()` releases the wrapped <xref:System.Management.ManagementObjectCollection> or <xref:System.Management.ManagementObjectCollection.ManagementObjectEnumerator> and its underlying COM-backed WMI resources deterministically.

## Version introduced

.NET 11 RC 2

## Previous behavior

The collection and enumerator types emitted by <xref:System.Management.ManagementClass.GetStronglyTypedClassCode*> did not implement <xref:System.IDisposable>. A generated collection could not be used in a `using` statement, and consumers could not deterministically release the WMI resources held by its wrapped <xref:System.Management.ManagementObjectCollection> or enumerator.

```csharp
// The generated ServiceCollection type did not implement IDisposable.
Service.ServiceCollection services = Service.GetInstances();
```

## New behavior

The generated collection and enumerator types implement <xref:System.IDisposable>. Consumers can dispose them to release the underlying WMI resources deterministically.

```csharp
using Service.ServiceCollection services = Service.GetInstances();

foreach (Service item in services)
{
// Use item.
}
```

Because the generated wrapper classes are non-sealed, adding `IDisposable` can affect code that derives from a generated wrapper and already declares a `Dispose` member or implements its own disposal pattern.

## Type of breaking change

This change can affect [source compatibility](../../categories.md#source-compatibility) and is a [behavioral change](../../categories.md#behavioral-change).

## Reason for change

The generated wrappers hold COM-backed WMI resources. This change exposes disposal behavior already supported by the wrapped <xref:System.Management> types so consumers can release those resources deterministically. The finalizer fallback of the wrapped types remains unchanged. For more information, see [dotnet/runtime#132587](https://github.com/dotnet/runtime/pull/132587).

## Recommended action

Regenerate your strongly typed WMI wrappers with the updated generator. Then dispose generated collection and enumerator wrappers when they are no longer needed, preferably with `using` or `using var`.

If your code derives from a generated collection or enumerator wrapper and already defines a disposal pattern, review the generated type's new `IDisposable` implementation. Update the derived type to avoid conflicting `Dispose` members and to preserve disposal of both its own resources and the base wrapper's resources.

## Affected APIs

- <xref:System.Management.ManagementClass.GetStronglyTypedClassCode*?displayProperty=nameWithType> generated collection types
- <xref:System.Management.ManagementClass.GetStronglyTypedClassCode*?displayProperty=nameWithType> generated enumerator types
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
title: "Breaking change: Empty strings in chained configuration override earlier providers"
description: "Learn about the breaking change in .NET 11 where an empty string in a chained configuration overrides earlier providers."
ms.date: 10/27/2026
ai-usage: ai-assisted
---

# Empty strings in chained configuration override earlier providers

Starting in .NET 11, a configuration added by using `AddConfiguration` treats an empty string as a present value. The empty string therefore overrides values from providers registered earlier in the outer configuration instead of allowing those earlier values to remain effective.

This change continues the distinction between empty and `null` configuration values established in .NET 10 by [Null values preserved in configuration](../10.0/configuration-null-values-preserved.md). The handling of `null` by chained configuration is unchanged.

## Version introduced

.NET 11 RC 1

## Previous behavior

`ChainedConfigurationProvider.TryGet` reported an empty string as not found. Consequently, an empty value in a chained configuration did not override a value supplied by an earlier provider:

```csharp
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;

IConfiguration inner = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
["Endpoint"] = "",
})
.Build();

IConfiguration configuration = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
["Endpoint"] = "https://example.com",
})
.AddConfiguration(inner)
.Build();

Console.WriteLine($"Endpoint: '{configuration["Endpoint"]}'");
```

Before .NET 11, the output was:

```text
Endpoint: 'https://example.com'
```

When there was no earlier value, reading the key returned `null`, and a section whose only value was the chained empty string was considered not to exist.

## New behavior

Starting in .NET 11, `ChainedConfigurationProvider.TryGet` reports an empty string as found. With the preceding example, the empty value from `inner` overrides the earlier value, and the output is:

```text
Endpoint: ''
```

A section whose value is an empty string is now considered to exist. Binding also observes the empty value instead of an earlier provider's value. For example, binding an empty string over an earlier numeric value to an integer property throws `InvalidOperationException`, consistently with an empty value supplied by a directly added provider.

A `null` value in the wrapped `IConfiguration` continues to be treated as absent, because the `IConfiguration` indexer cannot distinguish a key whose value is `null` from a missing key.

## Type of breaking change

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

## Reason for change

An empty string is a valid configuration value. Treating it as missing made chained configuration inconsistent with directly added configuration providers and prevented applications from intentionally clearing or disabling a setting by overriding it with an empty string. The new behavior preserves the configuration provider's distinction between an empty value and an absent value. For more information, see [dotnet/runtime#131480](https://github.com/dotnet/runtime/pull/131480).

## Recommended action

If an empty string is intended to override an earlier value, no action is required.

If your app relied on an empty string in a chained configuration allowing an earlier provider's value to win, remove that key from the chained configuration or represent it as missing or `null`. Applications that bind chained values to non-string types should also validate or normalize empty values before binding if an empty value is not valid for the target type. There is no compatibility switch to restore the previous behavior.

## Affected APIs

- <xref:Microsoft.Extensions.Configuration.ChainedConfigurationProvider.TryGet*?displayProperty=fullName>
- <xref:Microsoft.Extensions.Configuration.ChainedBuilderExtensions.AddConfiguration*?displayProperty=fullName>
- <xref:Microsoft.Extensions.Configuration.ChainedConfigurationSource.Build*?displayProperty=fullName>
71 changes: 71 additions & 0 deletions docs/core/compatibility/sdk/11/aot-publish-skips-full-build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
title: "Breaking change: Full build skipped for Native AOT publish"
description: "Learn about the breaking change in .NET 11 where the .NET SDK only compiles intermediate assemblies for Native AOT publish and skips the full Build target."
ms.date: 10/27/2026
ai-usage: ai-assisted
---

# Full build skipped for Native AOT publish

Starting in .NET 11, the .NET SDK no longer executes the full `Build` target when publishing with Native AOT (`PublishAot=true`). Instead, the SDK executes only the minimum targets needed to compile the intermediate assembly and produce the AOT-compiled output.

## Version introduced

.NET 11 RC 2

## Previous behavior

When publishing with `PublishAot=true`, the full MSBuild `Build` target executed as part of the publish pipeline, producing a complete self-contained managed deployment (apphost, DLLs, `deps.json`, `runtimeconfig.json`, and runtime pack files) in the output (`bin\`) directory. These artifacts were unused by the AOT pipeline, which reads from `@(IntermediateAssembly)` in `obj\`, not from `bin\`.

## New behavior

The .NET SDK runs only the targets needed to compile the intermediate assembly and produce the Native AOT publish output. It no longer runs the full `Build` target or produces the unused managed deployment in `bin\`.

Consequently, build extensibility points that aren't part of compilation don't run during Native AOT publish. These include `BeforeBuild`, `AfterBuild`, `PreBuildEvent`, `PostBuildEvent`, `BeforeTargets="Build"`, `AfterTargets="Build"`, and targets added to `BuildDependsOn`.

## Type of breaking change

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

## Reason for change

This change reduces customer confusion about which binaries to deploy and improves Native AOT publish performance. Deployable binaries are produced only in the publish directory.

## Recommended action

Update custom MSBuild targets to attach to the specific phase whose outputs they affect:

- For generated source or other compiler inputs, use `BeforeTargets="CoreCompile"`.
- For logic that consumes the compiled assembly, use `AfterTargets="Compile"` and consume `@(IntermediateAssembly)` rather than `$(TargetPath)`.
- For additional files that should be copied to the publish directory, declare them as `Content` items with `CopyToPublishDirectory`, or add them to `@(ResolvedFileToPublish)` before `ComputeResolvedFilesToPublishList`.
- For logic that processes the completed publish output, use `AfterTargets="Publish"`.

For example:

```xml
<Target Name="GenerateSources" BeforeTargets="CoreCompile">
<!-- Generate source and add it to @(Compile). -->
</Target>

<Target Name="ProcessCompiledAssembly" AfterTargets="Compile">
<!-- Consume @(IntermediateAssembly), which is produced in obj\. -->
</Target>
```

Targets that require the managed deployment previously produced in `bin\` can't use optimized publish. To restore the previous behavior, set `UseOptimizedPublish` to `false` in the project file:

```xml
<PropertyGroup>
<UseOptimizedPublish>false</UseOptimizedPublish>
</PropertyGroup>
```

Alternatively, pass it on the command line:

```dotnetcli
dotnet publish /p:UseOptimizedPublish=false
```

## Affected APIs

None.
6 changes: 6 additions & 0 deletions docs/core/compatibility/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ items:
href: core-libraries/11/environment-getcommandlineargs-apphost-invocation-name.md
- name: Environment.TickCount made consistent with Windows timeout behavior
href: core-libraries/11/environment-tickcount-windows-behavior.md
- name: Generated WMI collection and enumerator wrappers implement IDisposable
href: core-libraries/11/wmi-wrappers-implement-idisposable.md
- name: Math.Round and MathF.Round return correctly rounded results
href: core-libraries/11/math-round-digits.md
- name: Named mutexes default to user scope on Unix
Expand Down Expand Up @@ -74,6 +76,8 @@ items:
href: extensions/11/changetoken-onchange-async-overloads-rebind-callbacks.md
- name: Dependency injection scope disposal aggregates exceptions
href: extensions/11/dependency-injection-disposal-exceptions.md
- name: Empty strings in chained configuration override earlier providers
href: extensions/11/chained-configuration-empty-string.md
- name: FileConfigurationProvider doesn't raise reload token after ignored load failure
href: extensions/11/fileconfigurationprovider-reload-token-load-failure.md
- name: FileConfigurationSource.OnLoadException callback is called for IO errors
Expand Down Expand Up @@ -138,6 +142,8 @@ items:
items:
- name: dnx scripts bypass global.json SDK selection
href: sdk/11/dnx-scripts-bypass-global-json.md
- name: Full build skipped for Native AOT publish
href: sdk/11/aot-publish-skips-full-build.md
- name: mono launch target not set for .NET Framework apps
href: sdk/11/mono-launch-target-removed.md
- name: NativeAOT CLI command handling enabled by default
Expand Down
1 change: 1 addition & 0 deletions docs/csharp/fundamentals/building-software/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ The articles that follow use comparisons like these to explain when each approac

## Next steps

- [Tutorial: Combine C# techniques to generate badge labels](../tutorials/functional-techniques.md)
- [Pass behavior with lambda expressions](lambdas.md)
- [Organize helper logic with local functions](local-functions.md)
- [Produce sequences with iterators](iterators.md)
Loading
Loading