diff --git a/src/libraries/System.Diagnostics.Debug/tests/DebugTestsNoListeners.Interpolation.cs b/src/libraries/System.Diagnostics.Debug/tests/DebugTestsNoListeners.Interpolation.cs
index cd05cdfdc8bd13..d36acad1f825af 100644
--- a/src/libraries/System.Diagnostics.Debug/tests/DebugTestsNoListeners.Interpolation.cs
+++ b/src/libraries/System.Diagnostics.Debug/tests/DebugTestsNoListeners.Interpolation.cs
@@ -16,21 +16,30 @@ public void Asserts_Interpolation()
bool shouldAppend;
message = new Debug.AssertInterpolatedStringHandler(0, 0, true, out shouldAppend);
- VerifyLogged(() => Debug.Assert(true, message), "");
+ VerifyLogged(() => Debug.Assert(true, ref message), "");
message = new Debug.AssertInterpolatedStringHandler(0, 0, true, out shouldAppend);
detailedMessage = new Debug.AssertInterpolatedStringHandler(0, 0, true, out shouldAppend);
- VerifyLogged(() => Debug.Assert(true, message, detailedMessage), "");
+ VerifyLogged(() => Debug.Assert(true, ref message, ref detailedMessage), "");
message = new Debug.AssertInterpolatedStringHandler(0, 0, false, out shouldAppend);
- message.AppendLiteral("assert passed");
- VerifyAssert(() => Debug.Assert(false, message), "assert passed");
+ message.AppendLiteral("uh oh");
+ VerifyAssert(() => Debug.Assert(false, ref message), "uh oh");
message = new Debug.AssertInterpolatedStringHandler(0, 0, false, out shouldAppend);
- message.AppendLiteral("assert passed");
+ message.AppendLiteral("uh oh");
detailedMessage = new Debug.AssertInterpolatedStringHandler(0, 0, false, out shouldAppend);
- detailedMessage.AppendLiteral("nothing is wrong");
- VerifyAssert(() => Debug.Assert(false, message, detailedMessage), "assert passed", "nothing is wrong");
+ detailedMessage.AppendLiteral("something went wrong");
+ VerifyAssert(() => Debug.Assert(false, ref message, ref detailedMessage), "uh oh", "something went wrong");
+ }
+
+ [Fact]
+ public void Asserts_Interpolation_Syntax()
+ {
+ VerifyLogged(() => Debug.Assert(true, $"you won't see this {EmptyToString.Instance}"), "");
+ VerifyLogged(() => Debug.Assert(true, $"you won't see this {EmptyToString.Instance}", $"you won't see this {EmptyToString.Instance}"), "");
+ VerifyAssert(() => Debug.Assert(false, $"uh oh{EmptyToString.Instance}"), "uh oh");
+ VerifyAssert(() => Debug.Assert(false, $"uh oh{EmptyToString.Instance}", $"something went wrong{EmptyToString.Instance}"), "uh oh", "something went wrong");
}
[Fact]
@@ -41,21 +50,31 @@ public void WriteIf_Interpolation()
handler = new Debug.WriteIfInterpolatedStringHandler(0, 0, true, out shouldAppend);
handler.AppendLiteral("logged");
- VerifyLogged(() => Debug.WriteIf(true, handler), "logged");
+ VerifyLogged(() => Debug.WriteIf(true, ref handler), "logged");
handler = new Debug.WriteIfInterpolatedStringHandler(0, 0, false, out shouldAppend);
- VerifyLogged(() => Debug.WriteIf(false, handler), "");
+ VerifyLogged(() => Debug.WriteIf(false, ref handler), "");
handler = new Debug.WriteIfInterpolatedStringHandler(0, 0, true, out shouldAppend);
handler.AppendLiteral("logged");
- VerifyLogged(() => Debug.WriteIf(true, handler, "category"), "category: logged");
+ VerifyLogged(() => Debug.WriteIf(true, ref handler, "category"), "category: logged");
handler = new Debug.WriteIfInterpolatedStringHandler(0, 0, false, out shouldAppend);
- VerifyLogged(() => Debug.WriteIf(false, handler, "category"), "");
+ VerifyLogged(() => Debug.WriteIf(false, ref handler, "category"), "");
GoToNextLine();
}
+ [Fact]
+ public void WriteIf_Interpolation_Syntax()
+ {
+ VerifyLogged(() => Debug.WriteIf(true, $"{EmptyToString.Instance}logged"), "logged");
+ VerifyLogged(() => Debug.WriteIf(false, $"{EmptyToString.Instance}logged"), "");
+ VerifyLogged(() => Debug.WriteIf(true, $"{EmptyToString.Instance}logged", "category"), "category: logged");
+ VerifyLogged(() => Debug.WriteIf(false, $"{EmptyToString.Instance}logged", "category"), "");
+ GoToNextLine();
+ }
+
[Fact]
public void WriteLineIf_Interpolation()
{
@@ -64,17 +83,27 @@ public void WriteLineIf_Interpolation()
handler = new Debug.WriteIfInterpolatedStringHandler(0, 0, true, out shouldAppend);
handler.AppendLiteral("logged");
- VerifyLogged(() => Debug.WriteLineIf(true, handler), "logged" + Environment.NewLine);
+ VerifyLogged(() => Debug.WriteLineIf(true, ref handler), "logged" + Environment.NewLine);
handler = new Debug.WriteIfInterpolatedStringHandler(0, 0, false, out shouldAppend);
- VerifyLogged(() => Debug.WriteLineIf(false, handler), "");
+ VerifyLogged(() => Debug.WriteLineIf(false, ref handler), "");
handler = new Debug.WriteIfInterpolatedStringHandler(0, 0, true, out shouldAppend);
handler.AppendLiteral("logged");
- VerifyLogged(() => Debug.WriteLineIf(true, handler, "category"), "category: logged" + Environment.NewLine);
+ VerifyLogged(() => Debug.WriteLineIf(true, ref handler, "category"), "category: logged" + Environment.NewLine);
handler = new Debug.WriteIfInterpolatedStringHandler(0, 0, false, out shouldAppend);
- VerifyLogged(() => Debug.WriteLineIf(false, handler, "category"), "");
+ VerifyLogged(() => Debug.WriteLineIf(false, ref handler, "category"), "");
+ }
+
+ [Fact]
+ public void WriteLineIf_Interpolation_Syntax()
+ {
+ VerifyLogged(() => Debug.WriteLineIf(true, $"{EmptyToString.Instance}logged"), "logged" + Environment.NewLine);
+ VerifyLogged(() => Debug.WriteLineIf(false, $"{EmptyToString.Instance}logged"), "");
+ VerifyLogged(() => Debug.WriteLineIf(true, $"{EmptyToString.Instance}logged", "category"), "category: logged" + Environment.NewLine);
+ VerifyLogged(() => Debug.WriteLineIf(false, $"{EmptyToString.Instance}logged", "category"), "");
+ GoToNextLine();
}
[Theory]
@@ -131,7 +160,7 @@ public void DebugHandler_AppendOverloads_MatchStringBuilderHandler()
actual.AppendFormatted((object)DayOfWeek.Monday, 42, null);
expected.AppendFormatted((object)DayOfWeek.Monday, 42, null);
- VerifyAssert(() => Debug.Assert(false, actual), sb.ToString());
+ VerifyAssert(() => Debug.Assert(false, ref actual), sb.ToString());
}
[Fact]
@@ -174,7 +203,13 @@ public void WriteIfHandler_AppendOverloads_MatchStringBuilderHandler()
actual.AppendFormatted((object)DayOfWeek.Monday, 42, null);
expected.AppendFormatted((object)DayOfWeek.Monday, 42, null);
- VerifyLogged(() => Debug.WriteIf(true, actual), sb.ToString());
+ VerifyLogged(() => Debug.WriteIf(true, ref actual), sb.ToString());
+ }
+
+ private sealed class EmptyToString
+ {
+ public static EmptyToString Instance { get; } = new EmptyToString();
+ public override string ToString() => "";
}
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Debug.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Debug.cs
index 317e319e3f90a5..337f1491ae1d4e 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Debug.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Debug.cs
@@ -87,8 +87,8 @@ public static void Assert([DoesNotReturnIf(false)] bool condition, string? messa
Assert(condition, message, string.Empty);
[Conditional("DEBUG")]
- public static void Assert([DoesNotReturnIf(false)] bool condition, [InterpolatedStringHandlerArgument("condition")] AssertInterpolatedStringHandler message) =>
- Assert(condition, message.ToString());
+ public static void Assert([DoesNotReturnIf(false)] bool condition, [InterpolatedStringHandlerArgument("condition")] ref AssertInterpolatedStringHandler message) =>
+ Assert(condition, message.ToStringAndClear());
[Conditional("DEBUG")]
public static void Assert([DoesNotReturnIf(false)] bool condition, string? message, string? detailMessage)
@@ -100,8 +100,8 @@ public static void Assert([DoesNotReturnIf(false)] bool condition, string? messa
}
[Conditional("DEBUG")]
- public static void Assert([DoesNotReturnIf(false)] bool condition, [InterpolatedStringHandlerArgument("condition")] AssertInterpolatedStringHandler message, [InterpolatedStringHandlerArgument("condition")] AssertInterpolatedStringHandler detailMessage) =>
- Assert(condition, message.ToString(), detailMessage.ToString());
+ public static void Assert([DoesNotReturnIf(false)] bool condition, [InterpolatedStringHandlerArgument("condition")] ref AssertInterpolatedStringHandler message, [InterpolatedStringHandlerArgument("condition")] ref AssertInterpolatedStringHandler detailMessage) =>
+ Assert(condition, message.ToStringAndClear(), detailMessage.ToStringAndClear());
[Conditional("DEBUG")]
public static void Assert([DoesNotReturnIf(false)] bool condition, string? message, string detailMessageFormat, params object?[] args) =>
@@ -197,8 +197,8 @@ public static void WriteIf(bool condition, string? message)
}
[Conditional("DEBUG")]
- public static void WriteIf(bool condition, [InterpolatedStringHandlerArgument("condition")] WriteIfInterpolatedStringHandler message) =>
- WriteIf(condition, message.ToString());
+ public static void WriteIf(bool condition, [InterpolatedStringHandlerArgument("condition")] ref WriteIfInterpolatedStringHandler message) =>
+ WriteIf(condition, message.ToStringAndClear());
[Conditional("DEBUG")]
public static void WriteIf(bool condition, object? value)
@@ -219,8 +219,8 @@ public static void WriteIf(bool condition, string? message, string? category)
}
[Conditional("DEBUG")]
- public static void WriteIf(bool condition, [InterpolatedStringHandlerArgument("condition")] WriteIfInterpolatedStringHandler message, string? category) =>
- WriteIf(condition, message.ToString(), category);
+ public static void WriteIf(bool condition, [InterpolatedStringHandlerArgument("condition")] ref WriteIfInterpolatedStringHandler message, string? category) =>
+ WriteIf(condition, message.ToStringAndClear(), category);
[Conditional("DEBUG")]
public static void WriteIf(bool condition, object? value, string? category)
@@ -259,8 +259,8 @@ public static void WriteLineIf(bool condition, string? message)
}
[Conditional("DEBUG")]
- public static void WriteLineIf(bool condition, [InterpolatedStringHandlerArgument("condition")] WriteIfInterpolatedStringHandler message) =>
- WriteLineIf(condition, message.ToString());
+ public static void WriteLineIf(bool condition, [InterpolatedStringHandlerArgument("condition")] ref WriteIfInterpolatedStringHandler message) =>
+ WriteLineIf(condition, message.ToStringAndClear());
[Conditional("DEBUG")]
public static void WriteLineIf(bool condition, string? message, string? category)
@@ -272,8 +272,8 @@ public static void WriteLineIf(bool condition, string? message, string? category
}
[Conditional("DEBUG")]
- public static void WriteLineIf(bool condition, [InterpolatedStringHandlerArgument("condition")] WriteIfInterpolatedStringHandler message, string? category) =>
- WriteLineIf(condition, message.ToString(), category);
+ public static void WriteLineIf(bool condition, [InterpolatedStringHandlerArgument("condition")] ref WriteIfInterpolatedStringHandler message, string? category) =>
+ WriteLineIf(condition, message.ToStringAndClear(), category);
/// Provides an interpolated string handler for that only performs formatting if the assert fails.
[EditorBrowsable(EditorBrowsableState.Never)]
@@ -298,16 +298,21 @@ public AssertInterpolatedStringHandler(int literalLength, int formattedCount, bo
}
else
{
- _stringBuilderHandler = new StringBuilder.AppendInterpolatedStringHandler(literalLength, formattedCount, new StringBuilder(DefaultInterpolatedStringHandler.GetDefaultLength(literalLength, formattedCount)));
+ // Only used when failing an assert. Additional allocation here doesn't matter; just create a new StringBuilder.
+ _stringBuilderHandler = new StringBuilder.AppendInterpolatedStringHandler(literalLength, formattedCount, new StringBuilder());
shouldAppend = true;
}
}
/// Extracts the built string from the handler.
- internal new string ToString() =>
- _stringBuilderHandler._stringBuilder is StringBuilder sb ?
+ internal string ToStringAndClear()
+ {
+ string s = _stringBuilderHandler._stringBuilder is StringBuilder sb ?
sb.ToString() :
string.Empty;
+ _stringBuilderHandler = default;
+ return s;
+ }
/// Writes the specified string to the handler.
/// The string to write.
@@ -378,7 +383,9 @@ public WriteIfInterpolatedStringHandler(int literalLength, int formattedCount, b
{
if (condition)
{
- _stringBuilderHandler = new StringBuilder.AppendInterpolatedStringHandler(literalLength, formattedCount, new StringBuilder(DefaultInterpolatedStringHandler.GetDefaultLength(literalLength, formattedCount)));
+ // Only used in debug, but could be used on non-failure code paths, so use a cached builder.
+ _stringBuilderHandler = new StringBuilder.AppendInterpolatedStringHandler(literalLength, formattedCount,
+ StringBuilderCache.Acquire(DefaultInterpolatedStringHandler.GetDefaultLength(literalLength, formattedCount)));
shouldAppend = true;
}
else
@@ -389,10 +396,14 @@ public WriteIfInterpolatedStringHandler(int literalLength, int formattedCount, b
}
/// Extracts the built string from the handler.
- internal new string ToString() =>
- _stringBuilderHandler._stringBuilder is StringBuilder sb ?
- sb.ToString() :
+ internal string ToStringAndClear()
+ {
+ string s = _stringBuilderHandler._stringBuilder is StringBuilder sb ?
+ StringBuilderCache.GetStringAndRelease(sb) :
string.Empty;
+ _stringBuilderHandler = default;
+ return s;
+ }
/// Writes the specified string to the handler.
/// The string to write.
diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs
index a8ec06e1dfa738..5de2f8d1c1605d 100644
--- a/src/libraries/System.Runtime/ref/System.Runtime.cs
+++ b/src/libraries/System.Runtime/ref/System.Runtime.cs
@@ -8674,11 +8674,11 @@ public static void Assert([System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttrib
[System.Diagnostics.ConditionalAttribute("DEBUG")]
public static void Assert([System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute(false)] bool condition, string? message) { }
[System.Diagnostics.Conditional("DEBUG")]
- public static void Assert([System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute(false)] bool condition, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("condition")] System.Diagnostics.Debug.AssertInterpolatedStringHandler message) { }
+ public static void Assert([System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute(false)] bool condition, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("condition")] ref System.Diagnostics.Debug.AssertInterpolatedStringHandler message) { }
[System.Diagnostics.ConditionalAttribute("DEBUG")]
public static void Assert([System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute(false)] bool condition, string? message, string? detailMessage) { }
[System.Diagnostics.ConditionalAttribute("DEBUG")]
- public static void Assert([System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute(false)] bool condition, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("condition")] System.Diagnostics.Debug.AssertInterpolatedStringHandler message, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("condition")] System.Diagnostics.Debug.AssertInterpolatedStringHandler detailMessage) { }
+ public static void Assert([System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute(false)] bool condition, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("condition")] ref System.Diagnostics.Debug.AssertInterpolatedStringHandler message, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("condition")] ref System.Diagnostics.Debug.AssertInterpolatedStringHandler detailMessage) { }
[System.Diagnostics.ConditionalAttribute("DEBUG")]
public static void Assert([System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute(false)] bool condition, string? message, string detailMessageFormat, params object?[] args) { }
[System.Diagnostics.ConditionalAttribute("DEBUG")]
@@ -8714,11 +8714,11 @@ public static void WriteIf(bool condition, object? value, string? category) { }
[System.Diagnostics.ConditionalAttribute("DEBUG")]
public static void WriteIf(bool condition, string? message) { }
[System.Diagnostics.Conditional("DEBUG")]
- public static void WriteIf(bool condition, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("condition")] System.Diagnostics.Debug.WriteIfInterpolatedStringHandler message) { }
+ public static void WriteIf(bool condition, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("condition")] ref System.Diagnostics.Debug.WriteIfInterpolatedStringHandler message) { }
[System.Diagnostics.ConditionalAttribute("DEBUG")]
public static void WriteIf(bool condition, string? message, string? category) { }
[System.Diagnostics.Conditional("DEBUG")]
- public static void WriteIf(bool condition, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("condition")] System.Diagnostics.Debug.WriteIfInterpolatedStringHandler message, string? category) { }
+ public static void WriteIf(bool condition, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("condition")] ref System.Diagnostics.Debug.WriteIfInterpolatedStringHandler message, string? category) { }
[System.Diagnostics.ConditionalAttribute("DEBUG")]
public static void WriteLine(object? value) { }
[System.Diagnostics.ConditionalAttribute("DEBUG")]
@@ -8736,11 +8736,11 @@ public static void WriteLineIf(bool condition, object? value, string? category)
[System.Diagnostics.ConditionalAttribute("DEBUG")]
public static void WriteLineIf(bool condition, string? message) { }
[System.Diagnostics.ConditionalAttribute("DEBUG")]
- public static void WriteLineIf(bool condition, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("condition")] System.Diagnostics.Debug.WriteIfInterpolatedStringHandler message) { }
+ public static void WriteLineIf(bool condition, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("condition")] ref System.Diagnostics.Debug.WriteIfInterpolatedStringHandler message) { }
[System.Diagnostics.ConditionalAttribute("DEBUG")]
public static void WriteLineIf(bool condition, string? message, string? category) { }
[System.Diagnostics.ConditionalAttribute("DEBUG")]
- public static void WriteLineIf(bool condition, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("condition")] System.Diagnostics.Debug.WriteIfInterpolatedStringHandler message, string? category) { }
+ public static void WriteLineIf(bool condition, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("condition")] ref System.Diagnostics.Debug.WriteIfInterpolatedStringHandler message, string? category) { }
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.Runtime.CompilerServices.InterpolatedStringHandlerAttribute]
public struct AssertInterpolatedStringHandler