Skip to content

Commit

Permalink
.NET 10 Preview 1 breaking changes batch (#44625)
Browse files Browse the repository at this point in the history
* issues/44500

* Fix for 44500

* tweaks to 44500, issue 44403

* linting

* More 44500

* xref

* issue 44282

* xref fix

* issue 43952

* fix linting

* issue 43885

* issue 43828

* fix xref

* issue 43303

* issue 43284

* lint

* 43156

* issue 42558

* issue 42027

* build fix

* Apply suggestions from code review. Thank you @gewarren!

Co-authored-by: Genevieve Warren <[email protected]>

* Apply all new suggestions and AI disclosure

* Missed a couple suggestions

* Fixed linting issues introduced by VSCode

---------

Co-authored-by: Genevieve Warren <[email protected]>
  • Loading branch information
CamSoper and gewarren authored Jan 31, 2025
1 parent 4aaaae3 commit 6bad9ed
Show file tree
Hide file tree
Showing 16 changed files with 683 additions and 6 deletions.
33 changes: 29 additions & 4 deletions docs/core/compatibility/10.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
title: Breaking changes in .NET 10
titleSuffix: ""
description: Navigate to the breaking changes in .NET 10.
ms.date: 12/19/2024
ms.date: 01/30/2025
ai-usage: ai-assisted
no-loc: [Blazor, Razor, Kestrel]
---
# Breaking changes in .NET 10
Expand All @@ -17,6 +18,30 @@ If you're migrating an app to .NET 10, the breaking changes listed here might af
## Core .NET libraries

| Title | Type of change | Introduced version |
|------------------------------------------------------------------------------------------|---------------------|--------------------|
| [API obsoletions with non-default diagnostic IDs](core-libraries/10.0/obsolete-apis.md) | Source incompatible | Preview 1 |
| Title | Type of change | Introduced version |
|----------------------------------------------------------------------------------------------------------------------------|---------------------|--------------------|
| [API obsoletions with non-default diagnostic IDs](core-libraries/10.0/obsolete-apis.md) | Source incompatible | Preview 1 |
| [ActivitySource.CreateActivity and ActivitySource.StartActivity behavior change](core-libraries/10.0/activity-sampling.md) | Behavioral change | Preview 1 |
| [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 |
| [LDAP DirectoryControl parsing is now more stringent](core-libraries/10.0/ldap-directorycontrol-parsing.md) | Behavioral change | Preview 1 |
| [MacCatalyst version normalization](core-libraries/10.0/maccatalyst-version-normalization.md) | Behavioral change | Preview 1 |

## Globalization

| Title | Type of change | Introduced version |
|-------------------------------------------------------------------------------------------------------|-------------------|--------------------|
| [Environment variable renamed to DOTNET_ICU_VERSION_OVERRIDE](globalization/10.0/version-override.md) | Behavioral change | Preview 1 |

## Cryptography

| Title | Type of change | Introduced version |
|--------------------------------------------------------------------------------------------------------|-------------------|--------------------|
| [X500DistinguishedName validation is stricter](cryptography/10.0/x500distinguishedname-validation.md) | Behavioral change | Preview 1 |

## Windows Forms

| Title | Type of change | Introduced version |
|-------------------------------------------------------------------------------------------------------------------|---------------------|--------------------|
| [Renamed parameter in HtmlElement.InsertAdjacentElement](windows-forms/10.0/insertadjacentelement-orientation.md) | Source incompatible | Preview 1 |
| [TreeView checkbox image truncation](windows-forms/10.0/treeview-text-location.md) | Behavioral change | Preview 1 |
61 changes: 61 additions & 0 deletions docs/core/compatibility/core-libraries/10.0/activity-sampling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
title: "Breaking change: ActivitySource.CreateActivity and ActivitySource.StartActivity behavior changes"
description: Learn about the .NET 10.0 breaking change in core .NET libraries where ActivitySource.CreateActivity and ActivitySource.StartActivity behavior is modified.
ms.date: 01/30/2025
ai-usage: ai-assisted
---
# ActivitySource.CreateActivity and ActivitySource.StartActivity behavior change

The <xref:System.Diagnostics.ActivitySource.CreateActivity*?displayProperty=nameWithType> and <xref:System.Diagnostics.ActivitySource.StartActivity*?displayProperty=nameWithType> APIs only return an <xref:System.Diagnostics.Activity> when there's a registered listener that decides the instance should be created. This is generally known as sampling.

The <xref:System.Diagnostics.ActivitySamplingResult?displayProperty=nameWithType> enum defines the possible sampling decisions.

When creating an `Activity` without a parent, `ActivitySamplingResult` drives whether the `Activity` is created and then how the `Recorded` and `IsAllDataRequested` properties are set:

|ActivitySamplingResult|Activity created|Activity.Recorded|Activity.IsAllDataRequested|
|---|---|---|---|
|None|No|||
|PropagationData|Yes|False|False|
|AllData|Yes|False|True|
|AllDataAndRecorded|Yes|True|True|

It is also possible to create an `Activity` with a parent. The parent could be in the same process, or it could be a remote parent propagated to the current process.

## Previous behavior

Previously, when creating an `Activity` as `PropagationData` with a parent marked as `Recorded`, the `Recorded` and `IsAllDataRequested` properties were set as follows:

|ActivitySamplingResult|Activity created|Activity.Recorded|Activity.IsAllDataRequested|
|---|---|---|---|
|PropagationData|Yes|True|False|

## New behavior

Starting in .NET 10, when you create an `Activity` as `PropagationData` with a parent marked as `Recorded`, the `Recorded` and `IsAllDataRequested` properties are set as follows:

|ActivitySamplingResult|Activity created|Activity.Recorded|Activity.IsAllDataRequested|
|---|---|---|---|
|PropagationData|Yes|False|False|

## Version introduced

.NET 10 Preview 1

## Type of breaking change

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

## Reason for change

The previous behavior did not follow the OpenTelemetry specification.

## Recommended action

If you've implemented `ActivityListener.Sample` directly AND use `ActivitySamplingResult.PropagationData`, verify that you're not reliant on the flawed behavior. To restore the previous behavior, you can set `Activity.ActivityTraceFlags` to `Recorded` after the `CreateActivity` or `StartActivity` call.

If you use OpenTelemetry .NET and have customized the sampler, verify your sampler configuration. The default OpenTelemetry .NET configuration uses a parent-based algorithm that isn't impacted.

## Affected APIs

- <xref:System.Diagnostics.ActivitySource.CreateActivity*?displayProperty=fullName>
- <xref:System.Diagnostics.ActivitySource.StartActivity*?displayProperty=fullName>
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
title: "Breaking change: C# 14 overload resolution with span parameters"
description: Learn about the .NET 10 breaking change in core .NET libraries where overloads with span parameters are applicable in more scenarios.
ms.date: 01/30/2025
ai-usage: ai-assisted
---
# C# 14 overload resolution with span parameters

C# 14, which ships with .NET 10, introduces new [built-in span conversions and type inference rules](https://github.com/dotnet/csharplang/issues/7905). Those changes make overloads with span parameters applicable in more scenarios.

## Previous behavior

In C# 13 and earlier, an extension method taking a `ReadOnlySpan<T>` or `Span<T>` receiver was not applicable to a value of type `T[]`. Therefore, only non-span extension methods like the ones from the `System.Linq.Enumerable` class were usually bound inside Expression lambdas.

## New behavior

In C# 14 and later, methods with `ReadOnlySpan<T>` or `Span<T>` parameters can participate in type inference or be used as extension methods in more scenarios. This makes span-based methods like the ones from the `System.MemoryExtensions` class bind in more scenarios, including inside Expression lambdas where they will cause run-time exceptions when compiled with interpretation.

## Version introduced

.NET 10 Preview 1

## Type of breaking change

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

## Reason for change

The C# language feature allows simplified API design and usage (for example, one <xref:System.ReadOnlySpan`1> extension method can apply to both spans and arrays).

## Recommended action

If you need to continue using Expression interpretation, make sure the non-span overloads are bound, for example, by casting arguments to the exact types the method signature takes or calling the extension methods as explicit static invocations:

```csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

M((array, num) => array.Contains(num)); // fails, binds to MemoryExtensions.Contains
M((array, num) => ((IEnumerable<int>)array).Contains(num)); // ok, binds to Enumerable.Contains
M((array, num) => array.AsEnumerable().Contains(num)); // ok, binds to Enumerable.Contains
M((array, num) => Enumerable.Contains(array, num)); // ok, binds to Enumerable.Contains
void M(Expression<Func<int[], int, bool>> e) => e.Compile(preferInterpretation: true);
```

## Affected APIs

- <xref:System.Linq.Expressions.Expression`1.Compile*?displayProperty=fullName>
39 changes: 39 additions & 0 deletions docs/core/compatibility/core-libraries/10.0/generic-math.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
title: "Breaking change: Consistent shift behavior in generic math"
description: Learn about the .NET 10 breaking change in core .NET libraries where shift operations in generic math now have consistent behavior.
ms.date: 01/30/2025
ai-usage: ai-assisted
---
# Consistent shift behavior in generic math

Shift operations in generic math now have consistent behavior across all built-in integer types.

## Previous behavior

The behavior when utilizing generic math to perform a shift on a `T` could differ based on the type. In some cases, it appropriately masked the shift amount by `sizeof(T) - 1`. And in other cases, there was no masking. This meant that "overshifting" (such as shifting a `byte` by 8) could result in different answers than expected.

## New behavior

The implementations were updated to mask the shift amount, as appropriate, to ensure consistent behavior across all built-in integer types and with the behavior documented by the <xref:System.Numerics.IShiftOperators`3?displayProperty=nameWithType> interface.

## Version introduced

.NET 10 Preview 1

## Type of breaking change

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

## Reason for change

The behavior differed from the designed behavior due to a difference in how masking works for small integer types in C#.

## Recommended action

Update any code that relies on the previous inconsistent behavior to ensure it works with the new consistent behavior.

## Affected APIs

- `operator <<`
- `operator >>`
- `operator >>>` for `byte`, `char`, `sbyte`, `short`, and `ushort` when used via generic math, which requires a `T` constrained to `where T : IShiftOperators<T, int, T>` or a similar interface.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
title: "Breaking change: LDAP DirectoryControl parsing is now more stringent"
description: Learn about the .NET 10 breaking change in core .NET libraries where LDAP DirectoryControl parsing is now more stringent.
ms.date: 01/30/2025
ai-usage: ai-assisted
---

# LDAP DirectoryControl parsing is now more stringent

Previously, .NET used <xref:System.DirectoryServices.Protocols.BerConverter?displayProperty=nameWithType> to parse the <xref:System.DirectoryServices.Protocols.DirectoryControl?displayProperty=nameWithType> objects it received over the network and to generate the <xref:System.DirectoryServices.Protocols.DirectoryControl?displayProperty=nameWithType> byte arrays it sent. <xref:System.DirectoryServices.Protocols.BerConverter?displayProperty=nameWithType> used the OS-specific BER parsing functionality. This parsing functionality is now implemented in managed code.

## Previous behavior

As a result of using <xref:System.DirectoryServices.Protocols.BerConverter?displayProperty=nameWithType>, the parsing of <xref:System.DirectoryServices.Protocols.DirectoryControl?displayProperty=nameWithType> objects was fairly loose:

- The ASN.1 tags of each value weren't checked.
- Trailing data after the end of the parsed DirectoryControl was ignored, as was trailing data within an ASN.1 SEQUENCE.
- On Linux, OCTET STRING lengths that extended beyond the end of their parent sequence returned data outside the parent sequence.
- On earlier versions of Windows, a zero-length OCTET STRING returned `null` rather than an empty string.
- When reading the contents of a <xref:System.DirectoryServices.Protocols.DirectoryControl?displayProperty=nameWithType> as a UTF8-encoded string, an invalid UTF8 sequence did not throw an exception.
- When passing an invalid UTF8 string to the constructor of [VlvRequestControl](xref:System.DirectoryServices.Protocols.VlvRequestControl), no exception was thrown.

While not a breaking change, Windows always encoded ASN.1 tags with a four-byte length while Linux only used as many bytes for the tag length as it needed. Both representations were valid, but this behavioral difference between platforms is now gone; the Linux behavior now also appears on Windows.

## New behavior

The DirectoryControl parsing is much more stringent, and is now consistent across platforms and versions:

- ASN.1 tags are now checked.
- Trailing data is no longer permitted.
- The length of `OCTET STRING`s and `SEQUENCE`s is now checked.
- Zero-length `OCTET STRING`s now always return an empty string.
- If the server sends an invalid UTF8 byte sequence, the <xref:System.DirectoryServices.Protocols.DirectoryControl?displayProperty=nameWithType> parsing logic now throws an exception rather than silently substituting the invalid characters with a known value.

We also validate errors more thoroughly when calling the <xref:System.DirectoryServices.Protocols.VlvRequestControl> constructor. Passing a string which cannot be encoded as a UTF8 value now throws an <xref:System.Text.EncoderFallbackException>.

## Version introduced

.NET 10 Preview 1

## Type of breaking change

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

## Reason for change

This change was made for RFC and specification compliance. In the various RFCs and sections of MS-ADTS, the controlValue is specified as the BER encoding of an ASN.1 structure with wording similar to the following (from [RFC2891, section 1.2](https://datatracker.ietf.org/doc/html/rfc2891#section-1.2)):

> The controlType is set to "1.2.840.113556.1.4.474". The criticality is FALSE (MAY be absent). The controlValue is an OCTET STRING, whose value is the BER encoding of a value of the following SEQUENCE:
This precludes trailing data. It also rules out BER encodings of ASN.1 structures with differing ASN.1 tags, and of invalid BER encodings (such as OCTET STRINGs which are longer than their containing SEQUENCE.)

For the <xref:System.DirectoryServices.Protocols.VlvRequestControl> constructor, throwing the exception early means that users can trust that only the values they explicitly specify are sent to the server. There are no circumstances where they can accidentally send `EF BF BD` to the server because they've passed a string that can't be encoded to valid UTF8 bytes.

## Recommended action

Servers should comply with the RFCs and specifications. Make sure to handle an <xref:System.Text.EncoderFallbackException> when calling the <xref:System.DirectoryServices.Protocols.VlvRequestControl> constructor.

## Affected APIs

- <xref:System.DirectoryServices.Protocols.LdapConnection.SendRequest*?displayProperty=fullName>
- <xref:System.DirectoryServices.Protocols.LdapConnection.EndSendRequest*?displayProperty=fullName>
- <xref:System.DirectoryServices.Protocols.VlvRequestControl.%23ctor*>
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
title: "Breaking change: MacCatalyst version normalization"
description: Learn about the .NET 10 breaking change in core .NET libraries where MacCatalyst version components are normalized.
ms.date: 01/01/2025
ai-usage: ai-assisted
---

# MacCatalyst version normalization

This update ensures that MacCatalyst version components retrieved from the OS are always normalized to three components: major, minor, and build. The build component is set to `0` if undefined (`-1`), ensuring consistent behavior between iOS and MacCatalyst versions for version checks.

## Previous behavior

The build component in `Version` was not previously normalized, which led to incorrect version checks on MacCatalyst when only two components (major and minor) were provided. This resulted in invalid version checks.

## New behavior

The MacCatalyst build component is now normalized to `0`, ensuring consistent version checks. The revision component is always set to `-1`, as it is not specified on MacCatalyst or iOS.

## Version introduced

.NET 10 Preview 1

## Type of breaking change

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

## Reason for change

This changed was made to prevent incorrect version checks and align MacCatalyst versioning with iOS, ensuring consistent version components.

## Recommended action

Use versions of up to three components (major, minor, and build) on MacCatalyst.

## Affected APIs

- <xref:System.OperatingSystem.IsMacCatalystVersionAtLeast(System.Int32,System.Int32,System.Int32)?displayProperty=fullName>
- <xref:System.OperatingSystem.IsOSPlatformVersionAtLeast(System.String,System.Int32,System.Int32,System.Int32,System.Int32)?displayProperty=fullName>
- <xref:System.Environment.OSVersion?displayProperty=fullName>
Loading

0 comments on commit 6bad9ed

Please sign in to comment.