From 326d7becb59f963bc2c0dcc04352b09bae830599 Mon Sep 17 00:00:00 2001 From: Genevieve Warren <24882762+gewarren@users.noreply.github.com> Date: Thu, 3 Oct 2024 17:37:02 -0700 Subject: [PATCH 1/3] BinaryReader breaking change --- docs/core/compatibility/9.0.md | 1 + .../core-libraries/9.0/binaryreader.md | 58 +++++++++++++++++++ docs/core/compatibility/toc.yml | 4 ++ 3 files changed, 63 insertions(+) create mode 100644 docs/core/compatibility/core-libraries/9.0/binaryreader.md diff --git a/docs/core/compatibility/9.0.md b/docs/core/compatibility/9.0.md index 7b52fe2f7c208..446fe61fd4592 100644 --- a/docs/core/compatibility/9.0.md +++ b/docs/core/compatibility/9.0.md @@ -36,6 +36,7 @@ If you're migrating an app to .NET 9, the breaking changes listed here might aff | [Altered UnsafeAccessor support for non-open generics](core-libraries/9.0/unsafeaccessor-generics.md) | Behavioral change | Preview 6 | | [API obsoletions with custom diagnostic IDs](core-libraries/9.0/obsolete-apis-with-custom-diagnostics.md) | Source incompatible | Preview 16 | | [BigInteger maximum length](core-libraries/9.0/biginteger-limit.md) | Behavioral change | Preview 6 | +| [BinaryReader.GetString() returns "/uFFFD" on malformed sequences](core-libraries/9.0/binaryreader.md) | Behavioral change | Preview 7 | | [Creating type of array of System.Void not allowed](core-libraries/9.0/type-instance.md) | Behavioral change | Preview 1 | | [Default `Equals()` and `GetHashCode()` throw for types marked with `InlineArrayAttribute`](core-libraries/9.0/inlinearrayattribute.md) | Behavioral change | Preview 6 | | [FromKeyedServicesAttribute no longer injects non-keyed parameter](core-libraries/9.0/non-keyed-params.md) | Behavioral change | RC 1 | diff --git a/docs/core/compatibility/core-libraries/9.0/binaryreader.md b/docs/core/compatibility/core-libraries/9.0/binaryreader.md new file mode 100644 index 0000000000000..83ec957c6998b --- /dev/null +++ b/docs/core/compatibility/core-libraries/9.0/binaryreader.md @@ -0,0 +1,58 @@ +--- +title: "Breaking change:BinaryReader.GetString() returns "\uFFFD" on malformed sequences" +description: Learn about the .NET 9 breaking change in core .NET libraries where BinaryReader.GetString() returns "\uFFFD" on malformed encoded string sequences. +ms.date: 10/03/2024 +--- +# BinaryReader.GetString() returns "\uFFFD" on malformed sequences + +A a minor breaking change was introduced that only affects malformed encoded payloads. + +Prior to .NET 9, a malformed encoded string `[0x01, 0xC2]` that was parsed with returned an empty string. + +Starting in .NET 9, returns "\uFFFD", which is the `REPLACEMENT CHARACTER` used to replace an unknown, unrecognized, or unrepresentable character. This change only affects malformed payloads and matches Unicode standards. + +## Previous behavior + +```csharp +var ms = new MemoryStream(new byte[] { 0x01, 0xC2 }); +using (var br = new BinaryReader(ms)) +{ + string s = br.ReadString(); + Console.WriteLine(s == "\uFFFD"); // false + Console.WriteLine(s.Length); // 0 +} +``` + +## New behavior + +Starting in .NET 9, the same code snippet produces different results for `s == "\uFFFD"` and `s.Length`, as shown in the code comments: + +```csharp +var ms = new MemoryStream(new byte[] { 0x01, 0xC2 }); +using (var br = new BinaryReader(ms)) +{ + string s = br.ReadString(); + Console.WriteLine(s == "\uFFFD"); // true + Console.WriteLine(s.Length); // 1 +} +``` + +## Version introduced + +.NET 9 Preview 7 + +## Type of breaking change + +This change is a [behavioral change](../../categories.md#behavioral-change). + +## Reason for change + +This change was made as a performance improvement that affects a rare scenario. + +## Recommended action + +If you want to keep the previous behavior where incomplete byte sequence were omitted at the end of the string, call `TrimEnd("\uFFFD")` on the result. + +## Affected APIs + +- diff --git a/docs/core/compatibility/toc.yml b/docs/core/compatibility/toc.yml index 4f2b75d9a4586..33233b9c64421 100644 --- a/docs/core/compatibility/toc.yml +++ b/docs/core/compatibility/toc.yml @@ -150,6 +150,8 @@ items: href: core-libraries/8.0/file-path-backslash.md - name: Base64.DecodeFromUtf8 methods ignore whitespace href: core-libraries/8.0/decodefromutf8-whitespace.md + - name: BinaryReader.GetString() returns "/uFFFD" on malformed sequences + href: core-libraries/9.0/binaryreader.md - name: Boolean-backed enum type support removed href: core-libraries/8.0/bool-backed-enum.md - name: Complex.ToString format changed to `` @@ -1242,6 +1244,8 @@ items: href: core-libraries/9.0/obsolete-apis-with-custom-diagnostics.md - name: BigInteger maximum length href: core-libraries/9.0/biginteger-limit.md + - name: BinaryReader.GetString() returns "/uFFFD" on malformed sequences + href: core-libraries/9.0/binaryreader.md - name: Creating type of array of System.Void not allowed href: core-libraries/9.0/type-instance.md - name: "`Equals`/`GetHashCode` throw for `InlineArrayAttribute` types" From 1928363bf938f43a1de4dee8c0742a591d87efe8 Mon Sep 17 00:00:00 2001 From: Genevieve Warren <24882762+gewarren@users.noreply.github.com> Date: Thu, 3 Oct 2024 18:17:35 -0700 Subject: [PATCH 2/3] timespan.from overloads --- docs/core/compatibility/9.0.md | 1 + .../9.0/timespan-from-overloads.md | 52 +++++++++++++++++++ docs/core/compatibility/toc.yml | 4 ++ 3 files changed, 57 insertions(+) create mode 100644 docs/core/compatibility/core-libraries/9.0/timespan-from-overloads.md diff --git a/docs/core/compatibility/9.0.md b/docs/core/compatibility/9.0.md index 446fe61fd4592..0fc07844d35df 100644 --- a/docs/core/compatibility/9.0.md +++ b/docs/core/compatibility/9.0.md @@ -43,6 +43,7 @@ If you're migrating an app to .NET 9, the breaking changes listed here might aff | [IncrementingPollingCounter initial callback is asynchronous](core-libraries/9.0/async-callback.md) | Behavioral change | RC 1 | | [Inline array struct size limit is enforced](core-libraries/9.0/inlinearray-size.md) | Behavioral change | Preview 1 | | [InMemoryDirectoryInfo prepends rootDir to files](core-libraries/9.0/inmemorydirinfo-prepends-rootdir.md) | Behavioral change | Preview 1 | +| [New TimeSpan.From*() overloads that take integers](core-libraries/9.0/timespan-from-overloads.md) | Source incompatible | Preview 3 | | [RuntimeHelpers.GetSubArray returns different type](core-libraries/9.0/getsubarray-return.md) | Behavioral change | Preview 1 | | [Support for empty environment variables](core-libraries/9.0/empty-env-variable.md) | Behavioral change | Preview 6 | | [ZipArchiveEntry names and comments respect UTF8 flag](core-libraries/9.0/ziparchiveentry-encoding.md) | Behavioral change | RC 1 | diff --git a/docs/core/compatibility/core-libraries/9.0/timespan-from-overloads.md b/docs/core/compatibility/core-libraries/9.0/timespan-from-overloads.md new file mode 100644 index 0000000000000..fe0fff16414bc --- /dev/null +++ b/docs/core/compatibility/core-libraries/9.0/timespan-from-overloads.md @@ -0,0 +1,52 @@ +--- +title: "Breaking change: New TimeSpan.From*() overloads that take integers" +description: Learn about the .NET 9 breaking change in core .NET libraries where new TimeSpan.From*() overloads were introduced that take integer arguments. +ms.date: 10/03/2024 +--- +# New TimeSpan.From*() overloads that take integers + +New `TimeSpan.From*()` overloads that accept integers were introduced in .NET 9. This change can cause ambiguity for the F# compiler and result in compile-time errors. + +## Previous behavior + +Previously, there was a single overload for each `TimeSpan.From*()` method, namely: + +- +- +- +- +- +- +- + +## New behavior + +Starting in .NET 9, new overloads have been added that accept integer arguments. Calling a method such as `TimeSpan.FromMinutes(20)` in F# code results in a compile-time error: + +> error FS0041: A unique overload for method 'FromMinutes' could not be determined based on type information prior to this program point. A type annotation may be needed. Known type of argument: intCandidates: - TimeSpan.FromMinutes(minutes: int64) : TimeSpan - TimeSpan.FromMinutes(minutes: int64, ?seconds: int64, ?milliseconds: int64, ?microseconds: int64) : TimeSpan - TimeSpan.FromMinutes(value: float) : TimeSpan + +## Version introduced + +.NET 9 Preview 3 + +## Type of breaking change + +This change can affect [source compatibility](../../categories.md#source-compatibility) for F# code. + +## Reason for change + +The pre-existing overloads accepted a argument. However, is a binary-based, floating-point format and thus has natural imprecision that can introduce error. This behavior has led to user confusion and bugs in the API surface. It's also one of the less efficient ways to represent this data. To produce the intended behavior, new overloads were introduced that allow users to pass in integers. + +## Recommended action + +If this change affects your F# code, specify the type of argument so the compiler selects the appropriate overload. + +## Affected APIs + +- +- +- +- +- +- +- diff --git a/docs/core/compatibility/toc.yml b/docs/core/compatibility/toc.yml index 33233b9c64421..707a2a08873ab 100644 --- a/docs/core/compatibility/toc.yml +++ b/docs/core/compatibility/toc.yml @@ -40,6 +40,8 @@ items: href: core-libraries/9.0/inlinearray-size.md - name: InMemoryDirectoryInfo prepends rootDir to files href: core-libraries/9.0/inmemorydirinfo-prepends-rootdir.md + - name: New TimeSpan.From*() overloads that take integers + href: core-libraries/9.0/timespan-from-overloads.md - name: RuntimeHelpers.GetSubArray returns different type href: core-libraries/9.0/getsubarray-return.md - name: Support for empty environment variables @@ -1258,6 +1260,8 @@ items: href: core-libraries/9.0/inlinearray-size.md - name: InMemoryDirectoryInfo prepends rootDir to files href: core-libraries/9.0/inmemorydirinfo-prepends-rootdir.md + - name: New TimeSpan.From*() overloads that take integers + href: core-libraries/9.0/timespan-from-overloads.md - name: RuntimeHelpers.GetSubArray returns different type href: core-libraries/9.0/getsubarray-return.md - name: Support for empty environment variables From aef86f3377af0022702c2f2b0f094dced2b6d51e Mon Sep 17 00:00:00 2001 From: Genevieve Warren <24882762+gewarren@users.noreply.github.com> Date: Fri, 4 Oct 2024 10:05:51 -0700 Subject: [PATCH 3/3] fix build warnings --- docs/core/compatibility/core-libraries/9.0/binaryreader.md | 2 +- .../compatibility/core-libraries/9.0/timespan-from-overloads.md | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/core/compatibility/core-libraries/9.0/binaryreader.md b/docs/core/compatibility/core-libraries/9.0/binaryreader.md index 83ec957c6998b..c615900370335 100644 --- a/docs/core/compatibility/core-libraries/9.0/binaryreader.md +++ b/docs/core/compatibility/core-libraries/9.0/binaryreader.md @@ -1,5 +1,5 @@ --- -title: "Breaking change:BinaryReader.GetString() returns "\uFFFD" on malformed sequences" +title: "Breaking change:BinaryReader.GetString() returns '\uFFFD' on malformed sequences" description: Learn about the .NET 9 breaking change in core .NET libraries where BinaryReader.GetString() returns "\uFFFD" on malformed encoded string sequences. ms.date: 10/03/2024 --- diff --git a/docs/core/compatibility/core-libraries/9.0/timespan-from-overloads.md b/docs/core/compatibility/core-libraries/9.0/timespan-from-overloads.md index fe0fff16414bc..bd485d8d610d9 100644 --- a/docs/core/compatibility/core-libraries/9.0/timespan-from-overloads.md +++ b/docs/core/compatibility/core-libraries/9.0/timespan-from-overloads.md @@ -17,7 +17,6 @@ Previously, there was a single overload for each `TimeSpan.From*()` method, name - - - -- ## New behavior @@ -49,4 +48,3 @@ If this change affects your F# code, specify the type of argument so the compile - - - --