-
Notifications
You must be signed in to change notification settings - Fork 6.1k
Description
Description
It is very common to use interpolated strings with asserts, e.g.
Debug.Assert(result != x, $"Unexpected result {result}");However, this causes a string to be created for the message, including formatting result, on every call, even though typical use for asserts is that they're about something that should never happen.
C# 10 adds support for better string interpolation, including the ability to target custom "handlers" in addition to strings (see https://devblogs.microsoft.com/dotnet/string-interpolation-in-c-10-and-net-6/ for more details). In .NET 6, Debug has new overloads of Assert and WriteLine that utilize this functionality to conditionally evaluate the interpolated string formatting items only if the message is required. The C# compiler will prefer these new overloads, and thus if the formatting items were mutating state and the program was relying on those mutations to be visible even if the assert didn't fire, a difference in behavior could be observed.
Version
.NET 6 RC 1
Previous behavior
With:
Debug.Assert(true, $"{r.ToString()}");r.ToString() would always be invoked.
New behavior
With:
Debug.Assert(true, $"{r.ToString()}");r.ToString() will never be invoked, as the message is only needed if the condition is false.
Type of breaking change
- Binary incompatible: Existing binaries may encounter a breaking change in behavior, such as failure to load/execute or different run-time behavior.
- Source incompatible: Source code may encounter a breaking change in behavior when targeting the new runtime/component/SDK, such as compile errors or different run-time behavior.
Reason for change
Performance.
Recommended action
Interpolated strings used with Debug should not mutate shared state (these methods are all conditional on the DEBUG compilation constant as well). If for some reason it's critical that the old behavior be maintained, putting a (string) cast before the interpolated string will force the compiler to bind to the existing overload and will ensure the string is always materialized.
Feature area
Core .NET libraries
Affected APIs
Debug.Assert
Debug.WriteIf
Debug.WriteLineIf