-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: ArgumentException.ThrowIf
method
#99035
Comments
ArgumentException.ThrowIf
method
The lambda is going to add significant overhead. Argument validation is typically expected to be more light-weighted. If there's must-inline lambda like F#, this will be more acceptable. |
Sorry, I don't have that level of proficiency in .net, feel free to indicate me what performance-oriented changes should be done. |
The proper method would just be passing a boolean straight in. There's no reason to pass an immediately invoked delegate if one can just pass the result. Sure, there's no logical difference (program will execute the same) between these two blocks of code: void Test1(string str) {
ArgumentException.ThrowIf(x => x != "expected", str);
}
void Test2(string str) {
ArgumentException.ThrowIf(str != "expected", str);
} But the former ( The "correct" API would look like this: namespace System.Collections.Generic;
public class ArgumentException
{
public static void ThrowIf<T>(bool condition, T argument, string? message = null, [CallerArgumentExpression("argument")] string? paramName = null);
} Tangent: if your use case is to validate an // bad
void Test<T>(IEnumerable<T> source)
{
ArgumentException.ThrowIf(!source.Any(), source);
// this will cause multiple enumeration which incur performance issues or even exceptions
foreach (T element in source)
Use(element);
}
// good
void Test<T>(IEnumerable<T> source)
{
using IEnumerator<T> e = source.GetEnumerator();
if (!e.MoveNext())
throw new InvalidOperationException("Source is empty.");
do
{
Use(e.Current);
} while (e.MoveNext());
} |
But even then, this requires producing the message before the condition is checked, and that itself frequently has overheads, eg reading a string from a resx, or string.Fornat'ing a message. This has been discussed before in various forms. We have no plans to add such an overload. Just do |
Tagging subscribers to this area: @dotnet/area-system-runtime Issue DetailsBackground and motivationWe are seeing the creation of many helper methods to throw argument exceptions in a clean, one-liner way. But I feel it lacks one core method. The ability to throw argument exception by some condition. Check the difference in readability and "bloat" //current
public ExampleConstructor(int integer, string? str, char chr, Something? something, IService? service)
{
ArgumentOutOfRangeException.ThrowIfGreaterThan(integer, int.MaxValue / 2);
ArgumentException.ThrowIfNullOrWhiteSpace(str);
if (str.Equals("bad"))
{
throw new ArgumentException("This is a bad string", nameof(str));
}
if(char.IsLetter(chr))
{
throw new ArgumentException("Can not be a letter", nameof(chr));
}
ArgumentNullException.ThrowIfNull(something);
if (!something.CheckState)
{
throw new ArgumentException("Something, invalid state", nameof(something));
}
ArgumentNullException.ThrowIfNull(service);
if (!service.IsInitialized)
{
throw new ArgumentException("Service not initialized", nameof(service));
}
//Do things
}
//proposed
public ExampleConstructor(int integer, string? str, char chr, Something? something, IService? service)
{
ArgumentOutOfRangeException.ThrowIfGreaterThan(integer, int.MaxValue / 2);
ArgumentException.ThrowIfNullOrWhiteSpace(str);
ArgumentException.ThrowIf(IsBadString, str, "This is a bad string");
ArgumentException.ThrowIf(char.IsLetter, chr, "Can not be a letter");
ArgumentNullException.ThrowIfNull(something);
ArgumentException.ThrowIf(StateIsInvalid, something, "Something, invalid state");
ArgumentNullException.ThrowIfNull(service);
ArgumentException.ThrowIf(NotInitialized, service, "Service not initialized");
//Do things
}
private /*static*/ bool IsBadString(string str) => str.Equals("bad");
private /*static*/ bool StateIsInvalid(Something smt) => !smt.CheckState;
private /*static*/ bool NotInitilized(IService svc) => !svc.IsInitialized; And this can be used successfully to check things about IEnumerable (IsEmpty?, IsCountValid? AnyHasInvalidThings?, etc...) API Proposalnamespace System.Collections.Generic;
public class ArgumentException
{
public static void ThrowIf<T>(Func<T, bool> condition, T argument, string? message = null, [CallerArgumentExpression("argument")] string? paramName = null);
} API UsageThe example above. Alternative DesignsNone RisksI don't see any, except another method to mantain (but is a tiny method ;) )
|
Background and motivation
We are seeing the creation of many helper methods to throw argument exceptions in a clean, one-liner way. But I feel it lacks one core method. The ability to throw argument exception by some condition.
Check the difference in readability and "bloat"
And this can be used successfully to check things about IEnumerable (IsEmpty?, IsCountValid? AnyHasInvalidThings?, etc...)
API Proposal
API Usage
The example above.
Alternative Designs
None
Risks
I don't see any, except another method to mantain (but is a tiny method ;) )
The text was updated successfully, but these errors were encountered: