Closed
Description
Background and motivation
ArgumentOutOfRangeException
have read-only ActualValue
property which is settable only from constructor that also requires user provided message.
API Proposal
Unfortunately .ctor(string paramName, object actualValue)
is ambiguous if actualValue
is string
(because of existing .ctor(string paramName, string message)
), so I instead suggest new throw helper
namespace System;
public class ArgumentOutOfRangeException
{
[DoesNotReturn]
public static void Throw(object/*?*/ actualValue, [CallerArgumentExpression(nameof(actualValue))] string? paramName = null);
}
API Usage
void CheckEven(int i)
{
if (i % 2 != 0)
ArgumentOutOfRangeException.Throw(i);
}
Alternative Designs
Add factory method instead, this will allow creation of object without throwing (useful for testing).
Current workaround:
namespace System;
/// <inheritdoc />
public sealed class ArgumentOutOfRangeExceptionEx : ArgumentOutOfRangeException
{
private static readonly string Arg_ArgumentOutOfRangeException = (string)(typeof(ArgumentOutOfRangeException) // TODO: test on net40
.Assembly.GetType("System.SR")?
.GetProperty("Arg_ArgumentOutOfRangeException", // net core
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)
?.GetValue(null, null)
?? typeof(ArgumentOutOfRangeException)
.GetProperty("RangeMessage", // net fx
BindingFlags.Static | BindingFlags.NonPublic)
?.GetValue(null, null)
?? "Arg_ArgumentOutOfRangeException");
/// <summary>
/// Create <see cref="ArgumentOutOfRangeException"/> with default message
/// AND specifying <see cref="ArgumentOutOfRangeException.ActualValue"/>.
/// </summary>
/// <inheritdoc path='/param/[@name="paramName"]'/>
/// <inheritdoc path='/param/[@name="actualValue"]'/>
public ArgumentOutOfRangeExceptionEx(string paramName, object? actualValue)
: base(paramName, actualValue, Arg_ArgumentOutOfRangeException) { }
}
Risks
No response