From 490ed463e2e4bb859a5590cf8c2188c3fac423c5 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Thu, 23 Mar 2023 22:14:09 -0400 Subject: [PATCH 1/3] Add ArgumentOutOfRangeException.ThrowIf{Not}Equal --- .../InteropServices/InMemoryAssemblyLoader.cs | 3 +- .../src/Resources/Strings.resx | 3 - .../System/Dynamic/DynamicMetaObjectBinder.cs | 15 +--- .../Linq/Expressions/DebugInfoExpression.cs | 20 ++---- .../src/System/Linq/Expressions/Error.cs | 7 -- .../src/System/Linq/Expressions/Strings.cs | 5 -- .../NotifyCollectionChangedEventArgs.cs | 6 +- .../InteropServices/ComponentActivator.cs | 29 ++------ .../src/Resources/Strings.resx | 20 ++++-- .../src/System/ArgumentOutOfRangeException.cs | 71 +++++++++++-------- .../src/System/UriScheme.cs | 5 +- .../Dom/XmlNamedNodeMap.SmallXmlNodeList.cs | 9 +-- .../System/Xml/Schema/XmlSchemaCollection.cs | 15 ++-- .../System.Runtime/ref/System.Runtime.cs | 10 ++- .../ArgumentOutOfRangeExceptionTests.cs | 53 ++++++++++++++ 15 files changed, 139 insertions(+), 132 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/InMemoryAssemblyLoader.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/InMemoryAssemblyLoader.cs index c7c2e98a837bda..dc8d8ccb4c7cca 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/InMemoryAssemblyLoader.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/InMemoryAssemblyLoader.cs @@ -58,8 +58,7 @@ public static unsafe void LoadInMemoryAssemblyInContext(IntPtr moduleHandle, Int if (!IsSupported) throw new NotSupportedException(SR.NotSupported_CppCli); - if (loadContext != IntPtr.Zero) - throw new ArgumentOutOfRangeException(nameof(loadContext)); + ArgumentOutOfRangeException.ThrowIfNotEqual(loadContext, IntPtr.Zero); LoadInMemoryAssemblyInContextImpl(moduleHandle, assemblyPath, AssemblyLoadContext.Default); } diff --git a/src/libraries/System.Linq.Expressions/src/Resources/Strings.resx b/src/libraries/System.Linq.Expressions/src/Resources/Strings.resx index 4386b7c2fcd877..01f6ec7be8ddc5 100644 --- a/src/libraries/System.Linq.Expressions/src/Resources/Strings.resx +++ b/src/libraries/System.Linq.Expressions/src/Resources/Strings.resx @@ -396,9 +396,6 @@ Argument type cannot be System.Void. - - {0} must be greater than or equal to {1} - Cannot redefine label '{0}' in an inner block. diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObjectBinder.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObjectBinder.cs index 96157d4f793c51..9048b918b87af5 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObjectBinder.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObjectBinder.cs @@ -50,18 +50,9 @@ public sealed override Expression Bind(object[] args, ReadOnlyCollection endLine) { throw Error.StartEndMustBeOrdered(); diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Error.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Error.cs index f1869bda25cc84..aa0eac79d0a59d 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Error.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Error.cs @@ -1006,13 +1006,6 @@ internal static ArgumentException ArgumentCannotBeOfTypeVoid(string? paramName) return new ArgumentException(Strings.ArgumentCannotBeOfTypeVoid, paramName); } /// - /// ArgumentOutOfRangeException with message like "{0} must be greater than or equal to {1}" - /// - internal static ArgumentException OutOfRange(string? paramName, object? p1) - { - return new ArgumentOutOfRangeException(paramName, Strings.OutOfRange(paramName, p1)); - } - /// /// InvalidOperationException with message like "Cannot redefine label '{0}' in an inner block." /// internal static InvalidOperationException LabelTargetAlreadyDefined(object? p0) diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Strings.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Strings.cs index eb365167d4a112..b1f53512b8dcd3 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Strings.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Strings.cs @@ -643,11 +643,6 @@ internal static class Strings /// internal static string ArgumentCannotBeOfTypeVoid => SR.ArgumentCannotBeOfTypeVoid; - /// - /// A string like "{0} must be greater than or equal to {1}" - /// - internal static string OutOfRange(object? p0, object? p1) => SR.Format(SR.OutOfRange, p0, p1); - /// /// A string like "Cannot redefine label '{0}' in an inner block." /// diff --git a/src/libraries/System.ObjectModel/src/System/Collections/Specialized/NotifyCollectionChangedEventArgs.cs b/src/libraries/System.ObjectModel/src/System/Collections/Specialized/NotifyCollectionChangedEventArgs.cs index ef36f49b95fa52..4475eaf34e6a5e 100644 --- a/src/libraries/System.ObjectModel/src/System/Collections/Specialized/NotifyCollectionChangedEventArgs.cs +++ b/src/libraries/System.ObjectModel/src/System/Collections/Specialized/NotifyCollectionChangedEventArgs.cs @@ -328,11 +328,7 @@ public object? this[int index] { get { - if (index != 0) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - + ArgumentOutOfRangeException.ThrowIfNotEqual(index, 0); return _item; } set => throw new NotSupportedException(SR.NotSupported_ReadOnlyCollection); diff --git a/src/libraries/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComponentActivator.cs b/src/libraries/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComponentActivator.cs index 402d1a58d39f71..d543fc8c5d7916 100644 --- a/src/libraries/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComponentActivator.cs +++ b/src/libraries/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComponentActivator.cs @@ -76,11 +76,7 @@ public static unsafe int LoadAssemblyAndGetFunctionPointer(IntPtr assemblyPathNa string typeName = MarshalToString(typeNameNative, nameof(typeNameNative)); string methodName = MarshalToString(methodNameNative, nameof(methodNameNative)); - if (reserved != IntPtr.Zero) - { - throw new ArgumentOutOfRangeException(nameof(reserved)); - } - + ArgumentOutOfRangeException.ThrowIfNotEqual(reserved, IntPtr.Zero); ArgumentNullException.ThrowIfNull(functionHandle); // Set up the AssemblyLoadContext for this delegate. @@ -119,15 +115,8 @@ public static unsafe int LoadAssembly(IntPtr assemblyPathNative, IntPtr loadCont { string assemblyPath = MarshalToString(assemblyPathNative, nameof(assemblyPathNative)); - if (loadContext != IntPtr.Zero) - { - throw new ArgumentOutOfRangeException(nameof(loadContext)); - } - - if (reserved != IntPtr.Zero) - { - throw new ArgumentOutOfRangeException(nameof(reserved)); - } + ArgumentOutOfRangeException.ThrowIfNotEqual(loadContext, IntPtr.Zero); + ArgumentOutOfRangeException.ThrowIfNotEqual(reserved, IntPtr.Zero); LoadAssemblyLocal(assemblyPath); } @@ -215,16 +204,8 @@ public static unsafe int GetFunctionPointer(IntPtr typeNameNative, string typeName = MarshalToString(typeNameNative, nameof(typeNameNative)); string methodName = MarshalToString(methodNameNative, nameof(methodNameNative)); - if (loadContext != IntPtr.Zero) - { - throw new ArgumentOutOfRangeException(nameof(loadContext)); - } - - if (reserved != IntPtr.Zero) - { - throw new ArgumentOutOfRangeException(nameof(reserved)); - } - + ArgumentOutOfRangeException.ThrowIfNotEqual(loadContext, IntPtr.Zero); + ArgumentOutOfRangeException.ThrowIfNotEqual(reserved, IntPtr.Zero); ArgumentNullException.ThrowIfNull(functionHandle); #pragma warning disable IL2026 // suppressed in ILLink.Suppressions.LibraryBuild.xml diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index 3b6562ee595ef6..5c768231f9fdec 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -1929,25 +1929,31 @@ Year must be between 1 and 9999. - '{0}' must be a non-zero value. + {0} ('{1}') must be a non-zero value. - '{0}' must be a non-negative value. + {0} ('{1}') must be a non-negative value. - '{0}' must be a non-negative and non-zero value. + {0} ('{1}') must be a non-negative and non-zero value. - '{0}' must be less than or equal to '{1}'. + {0} ('{1}') must be less than or equal to '{2}'. - '{0}' must be less than '{1}'. + {0} ('{1}') must be less than '{2}'. - '{0}' must be greater than or equal to '{1}'. + {0} ('{1}') must be greater than or equal to '{2}'. - '{0}' must be greater than '{1}'. + {0} ('{1}') must be greater than '{2}'. + + + {0} ('{1}') must be equal to '{2}'. + + + {0} ('{1}') must not be equal to '{2}'. Function does not accept floating point Not-a-Number values. diff --git a/src/libraries/System.Private.CoreLib/src/System/ArgumentOutOfRangeException.cs b/src/libraries/System.Private.CoreLib/src/System/ArgumentOutOfRangeException.cs index 830a425a3caec3..d2ec8ca54f0878 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ArgumentOutOfRangeException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ArgumentOutOfRangeException.cs @@ -14,6 +14,7 @@ using System.Runtime.CompilerServices; using System.Diagnostics.CodeAnalysis; using System.Numerics; +using System.Collections.Generic; namespace System { @@ -90,46 +91,40 @@ public override string Message public virtual object? ActualValue => _actualValue; [DoesNotReturn] - private static void ThrowZero(string? paramName, T value) - { - throw new ArgumentOutOfRangeException(paramName, value, SR.Format(SR.ArgumentOutOfRange_Generic_MustBeNonZero, paramName)); - } + private static void ThrowZero(string? paramName, T value) => + throw new ArgumentOutOfRangeException(paramName, value, SR.Format(SR.ArgumentOutOfRange_Generic_MustBeNonZero, paramName, value)); [DoesNotReturn] - private static void ThrowNegative(string? paramName, T value) - { - throw new ArgumentOutOfRangeException(paramName, value, SR.Format(SR.ArgumentOutOfRange_Generic_MustBeNonNegative, paramName)); - } + private static void ThrowNegative(string? paramName, T value) => + throw new ArgumentOutOfRangeException(paramName, value, SR.Format(SR.ArgumentOutOfRange_Generic_MustBeNonNegative, paramName, value)); [DoesNotReturn] - private static void ThrowNegativeOrZero(string? paramName, T value) - { - throw new ArgumentOutOfRangeException(paramName, value, SR.Format(SR.ArgumentOutOfRange_Generic_MustBeNonNegativeNonZero, paramName)); - } + private static void ThrowNegativeOrZero(string? paramName, T value) => + throw new ArgumentOutOfRangeException(paramName, value, SR.Format(SR.ArgumentOutOfRange_Generic_MustBeNonNegativeNonZero, paramName, value)); [DoesNotReturn] - private static void ThrowGreater(string? paramName, T value, T other) - { - throw new ArgumentOutOfRangeException(paramName, value, SR.Format(SR.ArgumentOutOfRange_Generic_MustBeLessOrEqual, paramName, other)); - } + private static void ThrowGreater(string? paramName, T value, T other) => + throw new ArgumentOutOfRangeException(paramName, value, SR.Format(SR.ArgumentOutOfRange_Generic_MustBeLessOrEqual, paramName, value, other)); [DoesNotReturn] - private static void ThrowGreaterEqual(string? paramName, T value, T other) - { - throw new ArgumentOutOfRangeException(paramName, value, SR.Format(SR.ArgumentOutOfRange_Generic_MustBeLess, paramName, other)); - } + private static void ThrowGreaterEqual(string? paramName, T value, T other) => + throw new ArgumentOutOfRangeException(paramName, value, SR.Format(SR.ArgumentOutOfRange_Generic_MustBeLess, paramName, value, other)); [DoesNotReturn] - private static void ThrowLess(string? paramName, T value, T other) - { - throw new ArgumentOutOfRangeException(paramName, value, SR.Format(SR.ArgumentOutOfRange_Generic_MustBeGreaterOrEqual, paramName, other)); - } + private static void ThrowLess(string? paramName, T value, T other) => + throw new ArgumentOutOfRangeException(paramName, value, SR.Format(SR.ArgumentOutOfRange_Generic_MustBeGreaterOrEqual, paramName, value, other)); [DoesNotReturn] - private static void ThrowLessEqual(string? paramName, T value, T other) - { - throw new ArgumentOutOfRangeException(paramName, value, SR.Format(SR.ArgumentOutOfRange_Generic_MustBeGreater, paramName, other)); - } + private static void ThrowLessEqual(string? paramName, T value, T other) => + throw new ArgumentOutOfRangeException(paramName, value, SR.Format(SR.ArgumentOutOfRange_Generic_MustBeGreater, paramName, value, other)); + + [DoesNotReturn] + private static void ThrowEqual(string? paramName, T value, T other) => + throw new ArgumentOutOfRangeException(paramName, value, SR.Format(SR.ArgumentOutOfRange_Generic_MustBeNotEqual, paramName, (object?)value ?? "null", (object?)other ?? "null")); + + [DoesNotReturn] + private static void ThrowNotEqual(string? paramName, T value, T other) => + throw new ArgumentOutOfRangeException(paramName, value, SR.Format(SR.ArgumentOutOfRange_Generic_MustBeEqual, paramName, (object?)value ?? "null", (object?)other ?? "null")); /// Throws an if is zero. /// The argument to validate as non-zero. @@ -161,6 +156,26 @@ public static void ThrowIfNegativeOrZero(T value, [CallerArgumentExpression(n ThrowNegativeOrZero(paramName, value); } + /// Throws an if is equal to . + /// The argument to validate as not equal to . + /// The value to compare with . + /// The name of the parameter with which corresponds. + public static void ThrowIfEqual(T value, T other, [CallerArgumentExpression(nameof(value))] string? paramName = null) where T : IEquatable? + { + if (EqualityComparer.Default.Equals(value, other)) + ThrowEqual(paramName, value, other); + } + + /// Throws an if is not equal to . + /// The argument to validate as equal to . + /// The value to compare with . + /// The name of the parameter with which corresponds. + public static void ThrowIfNotEqual(T value, T other, [CallerArgumentExpression(nameof(value))] string? paramName = null) where T : IEquatable? + { + if (!EqualityComparer.Default.Equals(value, other)) + ThrowNotEqual(paramName, value, other); + } + /// Throws an if is greater than . /// The argument to validate as less or equal than . /// The value to compare with . diff --git a/src/libraries/System.Private.Uri/src/System/UriScheme.cs b/src/libraries/System.Private.Uri/src/System/UriScheme.cs index c9177b891371b3..c798b4f665b495 100644 --- a/src/libraries/System.Private.Uri/src/System/UriScheme.cs +++ b/src/libraries/System.Private.Uri/src/System/UriScheme.cs @@ -168,13 +168,12 @@ public static void Register(UriParser uriParser, string schemeName, int defaultP ArgumentNullException.ThrowIfNull(uriParser); ArgumentNullException.ThrowIfNull(schemeName); - if (schemeName.Length == 1) - throw new ArgumentOutOfRangeException(nameof(schemeName)); + ArgumentOutOfRangeException.ThrowIfEqual(schemeName.Length, 1); if (!Uri.CheckSchemeName(schemeName)) throw new ArgumentOutOfRangeException(nameof(schemeName)); - if ((defaultPort > 0xFFFF || defaultPort < 0) && defaultPort != -1) + if ((uint)defaultPort > 0xFFFF && defaultPort != -1) throw new ArgumentOutOfRangeException(nameof(defaultPort)); schemeName = schemeName.ToLowerInvariant(); diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Dom/XmlNamedNodeMap.SmallXmlNodeList.cs b/src/libraries/System.Private.Xml/src/System/Xml/Dom/XmlNamedNodeMap.SmallXmlNodeList.cs index 021941038895b4..914ae97f45551a 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Dom/XmlNamedNodeMap.SmallXmlNodeList.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Dom/XmlNamedNodeMap.SmallXmlNodeList.cs @@ -45,8 +45,7 @@ public object this[int index] if (list != null) return list[index]; - if (index != 0) - throw new ArgumentOutOfRangeException(nameof(index)); + ArgumentOutOfRangeException.ThrowIfNotEqual(index, 0); return _field; } @@ -97,8 +96,7 @@ public void RemoveAt(int index) return; } - if (index != 0) - throw new ArgumentOutOfRangeException(nameof(index)); + ArgumentOutOfRangeException.ThrowIfNotEqual(index, 0); _field = null; } @@ -107,8 +105,7 @@ public void Insert(int index, object value) { if (_field == null) { - if (index != 0) - throw new ArgumentOutOfRangeException(nameof(index)); + ArgumentOutOfRangeException.ThrowIfNotEqual(index, 0); Add(value); return; } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaCollection.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaCollection.cs index 918fc6c4348156..c9502b79877bb2 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaCollection.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaCollection.cs @@ -227,14 +227,11 @@ public XmlSchemaCollectionEnumerator GetEnumerator() void ICollection.CopyTo(Array array, int index) { ArgumentNullException.ThrowIfNull(array); - ArgumentOutOfRangeException.ThrowIfNegative(index); + for (XmlSchemaCollectionEnumerator e = this.GetEnumerator(); e.MoveNext();) { - if (index == array.Length) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } + ArgumentOutOfRangeException.ThrowIfEqual(index, array.Length); array.SetValue(e.Current, index++); } } @@ -242,18 +239,14 @@ void ICollection.CopyTo(Array array, int index) public void CopyTo(XmlSchema[] array, int index) { ArgumentNullException.ThrowIfNull(array); - ArgumentOutOfRangeException.ThrowIfNegative(index); + for (XmlSchemaCollectionEnumerator e = this.GetEnumerator(); e.MoveNext();) { XmlSchema? schema = e.Current; if (schema != null) { - if (index == array.Length) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - + ArgumentOutOfRangeException.ThrowIfEqual(index, array.Length); array[index++] = e.Current!; } } diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index bf955c2f418a77..c5e630e675110c 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -4,6 +4,8 @@ // Changes to this file must follow the https://aka.ms/api-review process. // ------------------------------------------------------------------------------ +using System.Runtime.CompilerServices; + namespace Microsoft.Win32.SafeHandles { public abstract partial class CriticalHandleMinusOneIsInvalid : System.Runtime.InteropServices.CriticalHandle @@ -301,13 +303,15 @@ public ArgumentOutOfRangeException(string? paramName, string? message) { } public virtual object? ActualValue { get { throw null; } } public override string Message { get { throw null; } } public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } - public static void ThrowIfZero(T value, [System.Runtime.CompilerServices.CallerArgumentExpressionAttribute(nameof(value))] string? paramName = null) where T : System.Numerics.INumberBase { throw null; } - public static void ThrowIfNegative(T value, [System.Runtime.CompilerServices.CallerArgumentExpressionAttribute(nameof(value))] string? paramName = null) where T : System.Numerics.INumberBase { throw null; } - public static void ThrowIfNegativeOrZero(T value, [System.Runtime.CompilerServices.CallerArgumentExpressionAttribute(nameof(value))] string? paramName = null) where T : System.Numerics.INumberBase { throw null; } + public static void ThrowIfEqual(T value, T other, [System.Runtime.CompilerServices.CallerArgumentExpression(nameof(value))] string? paramName = null) where T : IEquatable? { throw null; } public static void ThrowIfGreaterThan(T value, T other, [System.Runtime.CompilerServices.CallerArgumentExpressionAttribute(nameof(value))] string? paramName = null) where T : System.IComparable { throw null; } public static void ThrowIfGreaterThanOrEqual(T value, T other, [System.Runtime.CompilerServices.CallerArgumentExpressionAttribute(nameof(value))] string? paramName = null) where T : System.IComparable { throw null; } public static void ThrowIfLessThan(T value, T other, [System.Runtime.CompilerServices.CallerArgumentExpressionAttribute(nameof(value))] string? paramName = null) where T : System.IComparable { throw null; } public static void ThrowIfLessThanOrEqual(T value, T other, [System.Runtime.CompilerServices.CallerArgumentExpressionAttribute(nameof(value))] string? paramName = null) where T : System.IComparable { throw null; } + public static void ThrowIfNegative(T value, [System.Runtime.CompilerServices.CallerArgumentExpressionAttribute(nameof(value))] string? paramName = null) where T : System.Numerics.INumberBase { throw null; } + public static void ThrowIfNegativeOrZero(T value, [System.Runtime.CompilerServices.CallerArgumentExpressionAttribute(nameof(value))] string? paramName = null) where T : System.Numerics.INumberBase { throw null; } + public static void ThrowIfNotEqual(T value, T other, [System.Runtime.CompilerServices.CallerArgumentExpression(nameof(value))] string? paramName = null) where T : IEquatable? { throw null; } + public static void ThrowIfZero(T value, [System.Runtime.CompilerServices.CallerArgumentExpressionAttribute(nameof(value))] string? paramName = null) where T : System.Numerics.INumberBase { throw null; } } public partial class ArithmeticException : System.SystemException { diff --git a/src/libraries/System.Runtime/tests/System/ArgumentOutOfRangeExceptionTests.cs b/src/libraries/System.Runtime/tests/System/ArgumentOutOfRangeExceptionTests.cs index 777bf25f0fb03d..7fc6828e9dfdc4 100644 --- a/src/libraries/System.Runtime/tests/System/ArgumentOutOfRangeExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/ArgumentOutOfRangeExceptionTests.cs @@ -74,6 +74,8 @@ public static void Ctor_String_Object_String() private static Action GreaterThanOrEqualHelper(T value, T other) where T : IComparable => () => ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(value, other); private static Action LessThanHelper(T value, T other) where T : IComparable => () => ArgumentOutOfRangeException.ThrowIfLessThan(value, other); private static Action LessThanOrEqualHelper(T value, T other) where T : IComparable => () => ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(value, other); + private static Action EqualHelper(T value, T other) where T : IEquatable => () => ArgumentOutOfRangeException.ThrowIfEqual(value, other); + private static Action NotEqualHelper(T value, T other) where T : IEquatable => () => ArgumentOutOfRangeException.ThrowIfNotEqual(value, other); [Fact] public static void GenericHelpers_ThrowIfZero_Throws() @@ -86,6 +88,8 @@ public static void GenericHelpers_ThrowIfZero_Throws() Assert.Equal((double)0, AssertExtensions.Throws(HelpersParamName, ZeroHelper(0)).ActualValue); Assert.Equal(+0.0, AssertExtensions.Throws(HelpersParamName, ZeroHelper(+0.0)).ActualValue); Assert.Equal(-0.0, AssertExtensions.Throws(HelpersParamName, ZeroHelper(-0.0)).ActualValue); + + ZeroHelper(1)(); } [Fact] @@ -94,6 +98,8 @@ public static void GenericHelpers_ThrowIfNegativeZero_Throws() Assert.Equal(-1, AssertExtensions.Throws(HelpersParamName, NegativeOrZeroHelper(-1)).ActualValue); Assert.Equal(-0.0f, AssertExtensions.Throws(HelpersParamName, NegativeOrZeroHelper(-0.0f)).ActualValue); Assert.Equal(-0.0, AssertExtensions.Throws(HelpersParamName, NegativeOrZeroHelper(-0.0)).ActualValue); + + NegativeOrZeroHelper(1)(); } [Fact] @@ -103,6 +109,8 @@ public static void GenericHelpers_ThrowIfGreaterThan_Throws() Assert.Equal(1u, AssertExtensions.Throws(HelpersParamName, GreaterThanHelper(1, 0)).ActualValue); Assert.Equal(1.000000001, AssertExtensions.Throws(HelpersParamName, GreaterThanHelper(1.000000001, 1)).ActualValue); Assert.Equal(1.00001f, AssertExtensions.Throws(HelpersParamName, GreaterThanHelper(1.00001f, 1)).ActualValue); + + GreaterThanHelper(1, 2)(); } [Fact] @@ -112,6 +120,13 @@ public static void GenericHelpers_ThrowIfGreaterThanOrEqual_Throws() Assert.Equal(1u, AssertExtensions.Throws(HelpersParamName, GreaterThanOrEqualHelper(1, 1)).ActualValue); Assert.Equal((double)1, AssertExtensions.Throws(HelpersParamName, GreaterThanOrEqualHelper(1, 1)).ActualValue); Assert.Equal(1f, AssertExtensions.Throws(HelpersParamName, GreaterThanOrEqualHelper(1, 1)).ActualValue); + + Assert.Equal(3, AssertExtensions.Throws(HelpersParamName, GreaterThanOrEqualHelper(3, 1)).ActualValue); + Assert.Equal(4u, AssertExtensions.Throws(HelpersParamName, GreaterThanOrEqualHelper(4, 1)).ActualValue); + Assert.Equal((double)1.1, AssertExtensions.Throws(HelpersParamName, GreaterThanOrEqualHelper(1.1, 1)).ActualValue); + Assert.Equal(2.1f, AssertExtensions.Throws(HelpersParamName, GreaterThanOrEqualHelper(2.1f, 1)).ActualValue); + + GreaterThanOrEqualHelper(1, 2)(); } [Fact] @@ -121,15 +136,53 @@ public static void GenericHelpers_ThrowIfLessThan_Throws() Assert.Equal(0u, AssertExtensions.Throws(HelpersParamName, LessThanHelper(0, 1)).ActualValue); Assert.Equal((double)1, AssertExtensions.Throws(HelpersParamName, LessThanHelper(1, 1.000000001)).ActualValue); Assert.Equal(1f, AssertExtensions.Throws(HelpersParamName, LessThanHelper(1, 1.00001f)).ActualValue); + + LessThanHelper(2, 1)(); } [Fact] public static void GenericHelpers_ThrowIfLessThanOrEqual_Throws() { + Assert.Equal(-1, AssertExtensions.Throws(HelpersParamName, LessThanOrEqualHelper(-1, 1)).ActualValue); + Assert.Equal(0u, AssertExtensions.Throws(HelpersParamName, LessThanOrEqualHelper(0, 1)).ActualValue); + Assert.Equal((double)0.9, AssertExtensions.Throws(HelpersParamName, LessThanOrEqualHelper(0.9, 1)).ActualValue); + Assert.Equal(-0.1f, AssertExtensions.Throws(HelpersParamName, LessThanOrEqualHelper(-0.1f, 1)).ActualValue); + Assert.Equal(1, AssertExtensions.Throws(HelpersParamName, LessThanOrEqualHelper(1, 1)).ActualValue); Assert.Equal(1u, AssertExtensions.Throws(HelpersParamName, LessThanOrEqualHelper(1, 1)).ActualValue); Assert.Equal((double)1, AssertExtensions.Throws(HelpersParamName, LessThanOrEqualHelper(1, 1)).ActualValue); Assert.Equal(1f, AssertExtensions.Throws(HelpersParamName, LessThanOrEqualHelper(1, 1)).ActualValue); + + LessThanHelper(2, 1)(); + } + + [Fact] + public static void GenericHelpers_ThrowIfEqual_Throws() + { + Assert.Equal(1, AssertExtensions.Throws(HelpersParamName, EqualHelper(1, 1)).ActualValue); + Assert.Equal(1u, AssertExtensions.Throws(HelpersParamName, EqualHelper(1, 1)).ActualValue); + Assert.Equal((double)1, AssertExtensions.Throws(HelpersParamName, EqualHelper(1, 1)).ActualValue); + Assert.Equal(1f, AssertExtensions.Throws(HelpersParamName, EqualHelper(1, 1)).ActualValue); + Assert.Null(AssertExtensions.Throws(HelpersParamName, EqualHelper(null, null)).ActualValue); + + EqualHelper(1, 2)(); + EqualHelper("test1", "test2")(); + EqualHelper("test1", null)(); + EqualHelper(null, "test2")(); + } + + [Fact] + public static void GenericHelpers_ThrowIfNotEqual_Throws() + { + Assert.Equal(-1, AssertExtensions.Throws(HelpersParamName, NotEqualHelper(-1, 1)).ActualValue); + Assert.Equal(2u, AssertExtensions.Throws(HelpersParamName, NotEqualHelper(2, 1)).ActualValue); + Assert.Equal((double)2, AssertExtensions.Throws(HelpersParamName, NotEqualHelper(2, 1)).ActualValue); + Assert.Equal(1f, AssertExtensions.Throws(HelpersParamName, NotEqualHelper(1, 2)).ActualValue); + Assert.Equal("test", AssertExtensions.Throws(HelpersParamName, NotEqualHelper("test", null)).ActualValue); + Assert.Null(AssertExtensions.Throws(HelpersParamName, NotEqualHelper(null, "test")).ActualValue); + + NotEqualHelper(2, 2)(); + NotEqualHelper("test", "test")(); } } } From ed141b52209cd6128a6d6eb2d26cf618a4f40f27 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 28 Mar 2023 14:30:10 -0400 Subject: [PATCH 2/3] Address PR feedback --- .../src/System/Dynamic/DynamicMetaObjectBinder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObjectBinder.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObjectBinder.cs index 9048b918b87af5..7e39da3f5313d9 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObjectBinder.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObjectBinder.cs @@ -50,8 +50,8 @@ public sealed override Expression Bind(object[] args, ReadOnlyCollection Date: Wed, 5 Apr 2023 16:22:09 -0400 Subject: [PATCH 3/3] Address PR feedback --- src/libraries/System.Runtime/ref/System.Runtime.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index c5e630e675110c..1de1056254206d 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -4,8 +4,6 @@ // Changes to this file must follow the https://aka.ms/api-review process. // ------------------------------------------------------------------------------ -using System.Runtime.CompilerServices; - namespace Microsoft.Win32.SafeHandles { public abstract partial class CriticalHandleMinusOneIsInvalid : System.Runtime.InteropServices.CriticalHandle @@ -303,14 +301,14 @@ public ArgumentOutOfRangeException(string? paramName, string? message) { } public virtual object? ActualValue { get { throw null; } } public override string Message { get { throw null; } } public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } - public static void ThrowIfEqual(T value, T other, [System.Runtime.CompilerServices.CallerArgumentExpression(nameof(value))] string? paramName = null) where T : IEquatable? { throw null; } + public static void ThrowIfEqual(T value, T other, [System.Runtime.CompilerServices.CallerArgumentExpression(nameof(value))] string? paramName = null) where T : System.IEquatable? { throw null; } public static void ThrowIfGreaterThan(T value, T other, [System.Runtime.CompilerServices.CallerArgumentExpressionAttribute(nameof(value))] string? paramName = null) where T : System.IComparable { throw null; } public static void ThrowIfGreaterThanOrEqual(T value, T other, [System.Runtime.CompilerServices.CallerArgumentExpressionAttribute(nameof(value))] string? paramName = null) where T : System.IComparable { throw null; } public static void ThrowIfLessThan(T value, T other, [System.Runtime.CompilerServices.CallerArgumentExpressionAttribute(nameof(value))] string? paramName = null) where T : System.IComparable { throw null; } public static void ThrowIfLessThanOrEqual(T value, T other, [System.Runtime.CompilerServices.CallerArgumentExpressionAttribute(nameof(value))] string? paramName = null) where T : System.IComparable { throw null; } public static void ThrowIfNegative(T value, [System.Runtime.CompilerServices.CallerArgumentExpressionAttribute(nameof(value))] string? paramName = null) where T : System.Numerics.INumberBase { throw null; } public static void ThrowIfNegativeOrZero(T value, [System.Runtime.CompilerServices.CallerArgumentExpressionAttribute(nameof(value))] string? paramName = null) where T : System.Numerics.INumberBase { throw null; } - public static void ThrowIfNotEqual(T value, T other, [System.Runtime.CompilerServices.CallerArgumentExpression(nameof(value))] string? paramName = null) where T : IEquatable? { throw null; } + public static void ThrowIfNotEqual(T value, T other, [System.Runtime.CompilerServices.CallerArgumentExpression(nameof(value))] string? paramName = null) where T : System.IEquatable? { throw null; } public static void ThrowIfZero(T value, [System.Runtime.CompilerServices.CallerArgumentExpressionAttribute(nameof(value))] string? paramName = null) where T : System.Numerics.INumberBase { throw null; } } public partial class ArithmeticException : System.SystemException