Open
Description
openedon Aug 14, 2023
Edit Please vote by leaving 👍 if want them hidden 👎 if want to include them in stack traces
Currently, most throw helpers (like ArgumentNullException.ThrowIfNull(p)
) don't use the [StackTraceHidden]
, which makes them appear in stack traces. Some throw helpers are internally chained, which causes up to four additional frames. However, most are a single frame see all examples.
We have two options:
- Hide all throw helpers. Vote 👍
- Pro: Simpler stack traces
- Pro: First line in stack trace points to user code
- Con: Stack trace doesn't show which argument validation failed, you need to read message and/or look at the code
- Hide none of the throw helpers. Vote 👎
- Pro: Stack trace more accurately reflects reality
- Pro: Stack trace alone shows which argument validation failed
- Con: Stack trace is more noisy
There doesn't seem to be an argument that clearly shows one of the two options as superior. It's unlikely that we'll make the debugger configurable in this regard, so we'll have to pick one option, which is why user voting seems like a good way to decide.
Example code:
B(null!);
void B(string arg)
{
ArgumentException.ThrowIfNullOrEmpty(arg);
}
Current experience:
System.ArgumentNullException: Value cannot be null. (Parameter 'arg')
at System.ArgumentNullException.Throw(String paramName)
at System.ArgumentNullException.ThrowIfNull(Object argument, String paramName)
at System.ArgumentException.ThrowNullOrEmptyException(String argument, String paramName)
at System.ArgumentException.ThrowIfNullOrEmpty(String argument, String paramName)
at Program.<<Main>$>g__B|0_2(String arg) in C:\Users\thund\source\repos\ConsoleApp3\ConsoleApp3\Program.cs:line 26
at Program.<Main>$(String[] args) in C:\Users\thund\source\repos\ConsoleApp3\ConsoleApp3\Program.cs:line 10
Proposed experience:
System.ArgumentNullException: Value cannot be null. (Parameter 'arg')
at Program.<<Main>$>g__B|0_2(String arg) in C:\Users\thund\source\repos\ConsoleApp3\ConsoleApp3\Program.cs:line 26
at Program.<Main>$(String[] args) in C:\Users\thund\source\repos\ConsoleApp3\ConsoleApp3\Program.cs:line 10
API proposal (hidden because we first want users to vote on the experience)
namespace System;
public partial class ArgumentException : SystemException
{
[StackTraceHidden]
public static void ThrowIfNullOrEmpty([NotNull] string? argument, [CallerArgumentExpression("argument")] string? paramName = null);
[StackTraceHidden]
public static void ThrowIfNullOrWhiteSpace([NotNull] string? argument, [CallerArgumentExpression("argument")] string? paramName = null);
}
public partial class ArgumentOutOfRangeException : ArgumentException
{
[StackTraceHidden]
public static void ThrowIfEqual<T>(T value, T other, [CallerArgumentExpression("value")] string? paramName = null)
where T, IEquatable<T>?;
[StackTraceHidden]
public static void ThrowIfGreaterThan<T>(T value, T other, [CallerArgumentExpression("value")] string? paramName = null)
where T, IComparable<T>!;
[StackTraceHidden]
public static void ThrowIfGreaterThanOrEqual<T>(T value, T other, [CallerArgumentExpression("value")] string? paramName = null)
where T, IComparable<T>!;
[StackTraceHidden]
public static void ThrowIfLessThan<T>(T value, T other, [CallerArgumentExpression("value")] string? paramName = null)
where T, IComparable<T>!;
[StackTraceHidden]
public static void ThrowIfLessThanOrEqual<T>(T value, T other, [CallerArgumentExpression("value")] string? paramName = null)
where T, IComparable<T>!;
[StackTraceHidden]
public static void ThrowIfNegative<T>(T value, [CallerArgumentExpression("value")] string? paramName = null)
where T, INumberBase<T>!;
[StackTraceHidden]
public static void ThrowIfNegativeOrZero<T>(T value, [CallerArgumentExpression("value")] string? paramName = null)
where T, INumberBase<T>!;
[StackTraceHidden]
public static void ThrowIfNotEqual<T>(T value, T other, [CallerArgumentExpression("value")] string? paramName = null)
where T, IEquatable<T>?;
[StackTraceHidden]
public static void ThrowIfZero<T>(T value, [CallerArgumentExpression("value")] string? paramName = null)
where T, INumberBase<T>!;
}
// Already marked
public partial class ObjectDisposedException : InvalidOperationException
{
[StackTraceHidden]
public static void ThrowIf([DoesNotReturnIf(true)] bool condition, object! instance);
[StackTraceHidden]
public static void ThrowIf([DoesNotReturnIf(true)] bool condition, Type! type);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment