Skip to content

[API Proposal]: ArgumentOutOfRangeException constructor with actualValue and system message #89783

Closed
@OwnageIsMagic

Description

@OwnageIsMagic

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions