diff --git a/README.md b/README.md index fceb7cb..b04bb4c 100644 --- a/README.md +++ b/README.md @@ -5,23 +5,32 @@ Especially intended for projects with multiple `TargetFrameworks`, for usage, st ## Method Overview The following methods are currently provided. -### ThrowIfGreaterThan -Compatibility method to [`ArgumentOutOfRangeException.ThrowIfGreaterThan(T, T, String)`](https://learn.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception.throwifgreaterthan), which was introduced with .NET 8 +### `Argument.ThrowIfEqual(T, T, string?)` +Throws an `ArgumentOutOfRangeException` if the first argument is equal to the second argument. Inplace replacement for [`ArgumentOutOfRangeException.ThrowIfEqual(T, T, string)`](https://learn.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception.throwifequal), which was introduced with **.NET 8**. -### ThrowIfGreaterThanOrEqual -Compatibility method to [`ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(T, T, String)`](https://learn.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception.throwifgreaterthanorequal), which is part of the framework since .NET 8. +### `Argument.ThrowIfGreaterThan(T, T, string?)` +Throws an `ArgumentOutOfRangeException` if the first argument is greater than the second argument. Inplace replacement for [`ArgumentOutOfRangeException.ThrowIfGreaterThan(T, T, string)`](https://learn.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception.throwifgreaterthan), which was introduced with **.NET 8**. -### ThrowIfLessThan -Compatibility method to [`ArgumentOutOfRangeException.ThrowIfLessThan(T, T, String)`](https://learn.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception.throwiflessthan), which is part of the framework since .NET 8. +### `Argument.ThrowIfGreaterThanOrEqual(T, T, string?)` +Throws an `ArgumentOutOfRangeException` if the first argument is greater than or equal to the second argument. Inplace replacement for [`ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(T, T, string)`](https://learn.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception.throwifgreaterthanorequal), which was introduced with **.NET 8**. -### ThrowIfLessThanOrEqual -Compatibility method to [`ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(T, T, String)`](https://learn.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception.throwiflessthanorequal), which is part of the framework since .NET 8. +### `Argument.ThrowIfLessThan(T, T, string?)` +Throws an `ArgumentOutOfRangeException` if the first argument is less than the second argument. Inplace replacement for [`ArgumentOutOfRangeException.ThrowIfLessThan(T, T, string)`](https://learn.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception.throwiflessthan), which was introduced with **.NET 8**. -### ThrowIfNull -Compatibility method to [`ArgumentNullException.ThrowIfNull(Object, String)`](https://learn.microsoft.com/en-us/dotnet/api/system.argumentnullexception.throwifnull#system-argumentnullexception-throwifnull(system-object-system-string)), which is part of the framework since .NET 8. +### `Argument.ThrowIfLessThanOrEqual(T, T, string?)` +Throws an `ArgumentOutOfRangeException` if the first argument is less than or equal to the second argument. Inplace replacement for [`ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(T, T, string)`](https://learn.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception.throwiflessthanorequal), which was introduced with **.NET 8**. -### ThrowIfNullOrEmpty -Compatibility method to [`ArgumentException.ThrowIfNullOrEmpty(String, String)`](https://learn.microsoft.com/en-us/dotnet/api/system.argumentexception.throwifnullorempty), which is part of the framework since .NET 8. +### `Argument.ThrowIfNotEqual(T, T, string?)` +Throws an `ArgumentOutOfRangeException` if the first argument is not equal to the second argument. Inplace replacement for [`ArgumentOutOfRangeException.ThrowIfNotEqual(T, T, string)`](https://learn.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception.throwifnotequal), which was introduced with **.NET 8**. -### ThrowIfNullOrWhiteSpace -Compatibility method to [`ArgumentException.ThrowIfNullOrWhiteSpace(String, String)`](https://learn.microsoft.com/en-us/dotnet/api/system.argumentexception.throwifnullorwhitespace), which is part of the framework since .NET 8. +### `Argument.ThrowIfNull(object?, string?)` +Throws an `ArgumentNullException` if the argument is `null`. Inplace replacement for [`ArgumentNullException.ThrowIfNull(object, string)`](https://learn.microsoft.com/en-us/dotnet/api/system.argumentnullexception.throwifnull), which was introduced with **.NET 6**. + +### `Argument.ThrowIfNull(void*, string?)` +Throws an `ArgumentNullException` if the argument is `null`. Inplace replacement for [`ArgumentNullException.ThrowIfNull(void*, string)`](https://learn.microsoft.com/en-us/dotnet/api/system.argumentnullexception.throwifnull?view=net-8.0#system-argumentnullexception-throwifnull(system-void*-system-string), which was introduced with **.NET 7**. + +### `Argument.ThrowIfNullOrEmpty(string?, string?)` +Throws an `ArgumentNullException` if the argument is `null` or throws an `ArgumentException` if the argument is empty. Inplace replacement for [`ArgumentException.ThrowIfNullOrEmpty(string, string)`](https://learn.microsoft.com/en-us/dotnet/api/system.argumentexception.throwifnullorempty), which was introduced with **.NET 7**. + +### `Argument.ThrowIfNullOrWhiteSpace(string?, string?)` +Throws an `ArgumentNullException` if the argument is `null` or throws an `ArgumentException` if the argument is empty or contains only white-space characters. Inplace replacement for [`ArgumentException.ThrowIfNullOrWhiteSpace(string, string)`](https://learn.microsoft.com/en-us/dotnet/api/system.argumentexception.throwifnullorwhitespace), which was introduced with **.NET 8**. \ No newline at end of file diff --git a/src/NetEvolve.Arguments/Argument_ThrowArgumentException.cs b/src/NetEvolve.Arguments/Argument_ThrowArgumentException.cs index 7a9fc65..bc6f02f 100644 --- a/src/NetEvolve.Arguments/Argument_ThrowArgumentException.cs +++ b/src/NetEvolve.Arguments/Argument_ThrowArgumentException.cs @@ -12,9 +12,9 @@ public static partial class Argument [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] [StackTraceHidden] - private static void ThrowArgumentException(string? paramName) + private static void ThrowArgumentException(string? paramName, string? message = null) { - throw new ArgumentException(null, paramName); + throw new ArgumentException(message, paramName); } } #endif diff --git a/src/NetEvolve.Arguments/Argument_ThrowArgumentNullException.cs b/src/NetEvolve.Arguments/Argument_ThrowArgumentNullException.cs index 90f8ca8..d2f2fb8 100644 --- a/src/NetEvolve.Arguments/Argument_ThrowArgumentNullException.cs +++ b/src/NetEvolve.Arguments/Argument_ThrowArgumentNullException.cs @@ -12,9 +12,9 @@ public static partial class Argument [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] [StackTraceHidden] - private static void ThrowArgumentNullException(string? paramName) + private static void ThrowArgumentNullException(string? paramName, string? message = null) { - throw new ArgumentNullException(paramName); + throw new ArgumentNullException(paramName, message); } } #endif diff --git a/src/NetEvolve.Arguments/Argument_ThrowArgumentOutOfRangeException.cs b/src/NetEvolve.Arguments/Argument_ThrowArgumentOutOfRangeException.cs index 34650a2..fca31a5 100644 --- a/src/NetEvolve.Arguments/Argument_ThrowArgumentOutOfRangeException.cs +++ b/src/NetEvolve.Arguments/Argument_ThrowArgumentOutOfRangeException.cs @@ -12,10 +12,13 @@ public static partial class Argument [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] [StackTraceHidden] - private static void ThrowArgumentOutOfRangeException(string? paramName, T value) - where T : IComparable + private static void ThrowArgumentOutOfRangeException( + string? paramName, + T value, + string? message = null + ) { - throw new ArgumentOutOfRangeException(paramName, value, null); + throw new ArgumentOutOfRangeException(paramName, value, message); } } #endif diff --git a/src/NetEvolve.Arguments/Argument_ThrowIfEqual.cs b/src/NetEvolve.Arguments/Argument_ThrowIfEqual.cs new file mode 100644 index 0000000..dc41779 --- /dev/null +++ b/src/NetEvolve.Arguments/Argument_ThrowIfEqual.cs @@ -0,0 +1,41 @@ +namespace NetEvolve.Arguments; + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.CompilerServices; + +public static partial class Argument +{ + /// 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. + [DebuggerStepThrough] + [StackTraceHidden] +#if NET8_0_OR_GREATER + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#else + [MethodImpl(MethodImplOptions.NoInlining)] +#endif + public static void ThrowIfEqual( + T value, + T other, + [CallerArgumentExpression(nameof(value))] string? paramName = null + ) + where T : IEquatable + { +#if NET8_0_OR_GREATER + ArgumentOutOfRangeException.ThrowIfEqual(value, other, paramName); +#else + if (EqualityComparer.Default.Equals(value, other)) + { + ThrowArgumentOutOfRangeException( + paramName, + value, + $"{paramName} ('{value}') must not be equal to '{other}'." + ); + } +#endif + } +} diff --git a/src/NetEvolve.Arguments/Argument_ThrowIfGreaterThan.cs b/src/NetEvolve.Arguments/Argument_ThrowIfGreaterThan.cs index 7bb9828..dd5ecdc 100644 --- a/src/NetEvolve.Arguments/Argument_ThrowIfGreaterThan.cs +++ b/src/NetEvolve.Arguments/Argument_ThrowIfGreaterThan.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.Runtime.CompilerServices; public static partial class Argument @@ -30,7 +31,11 @@ public static void ThrowIfGreaterThan( #else if (value.CompareTo(other) > 0) { - ThrowArgumentOutOfRangeException(paramName, value); + ThrowArgumentOutOfRangeException( + paramName, + value, + $"{paramName} ('{value}') must be less than or equal to '{other}'." + ); } #endif } diff --git a/src/NetEvolve.Arguments/Argument_ThrowIfGreaterThanOrEqual.cs b/src/NetEvolve.Arguments/Argument_ThrowIfGreaterThanOrEqual.cs index c6b6607..58e0527 100644 --- a/src/NetEvolve.Arguments/Argument_ThrowIfGreaterThanOrEqual.cs +++ b/src/NetEvolve.Arguments/Argument_ThrowIfGreaterThanOrEqual.cs @@ -29,7 +29,11 @@ public static void ThrowIfGreaterThanOrEqual( #else if (value.CompareTo(other) >= 0) { - ThrowArgumentOutOfRangeException(paramName, value); + ThrowArgumentOutOfRangeException( + paramName, + value, + $"{paramName} ('{value}') must be less than '{other}'." + ); } #endif } diff --git a/src/NetEvolve.Arguments/Argument_ThrowIfLessThan.cs b/src/NetEvolve.Arguments/Argument_ThrowIfLessThan.cs index a9774dd..a263962 100644 --- a/src/NetEvolve.Arguments/Argument_ThrowIfLessThan.cs +++ b/src/NetEvolve.Arguments/Argument_ThrowIfLessThan.cs @@ -29,7 +29,11 @@ public static void ThrowIfLessThan( #else if (value.CompareTo(other) < 0) { - ThrowArgumentOutOfRangeException(paramName, value); + ThrowArgumentOutOfRangeException( + paramName, + value, + $"{paramName} ('{value}') must be greater than '{other}'." + ); } #endif } diff --git a/src/NetEvolve.Arguments/Argument_ThrowIfLessThanOrEqual.cs b/src/NetEvolve.Arguments/Argument_ThrowIfLessThanOrEqual.cs index ae95890..9db4f09 100644 --- a/src/NetEvolve.Arguments/Argument_ThrowIfLessThanOrEqual.cs +++ b/src/NetEvolve.Arguments/Argument_ThrowIfLessThanOrEqual.cs @@ -29,7 +29,11 @@ public static void ThrowIfLessThanOrEqual( #else if (value.CompareTo(other) <= 0) { - ThrowArgumentOutOfRangeException(paramName, value); + ThrowArgumentOutOfRangeException( + paramName, + value, + $"{paramName} ('{value}') must be greater than or equal to '{other}'." + ); } #endif } diff --git a/src/NetEvolve.Arguments/Argument_ThrowIfNotEqual.cs b/src/NetEvolve.Arguments/Argument_ThrowIfNotEqual.cs new file mode 100644 index 0000000..ac79346 --- /dev/null +++ b/src/NetEvolve.Arguments/Argument_ThrowIfNotEqual.cs @@ -0,0 +1,41 @@ +namespace NetEvolve.Arguments; + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.CompilerServices; + +public static partial class Argument +{ + /// 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. + [DebuggerStepThrough] + [StackTraceHidden] +#if NET8_0_OR_GREATER + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#else + [MethodImpl(MethodImplOptions.NoInlining)] +#endif + public static void ThrowIfNotEqual( + T value, + T other, + [CallerArgumentExpression(nameof(value))] string? paramName = null + ) + where T : IEquatable + { +#if NET8_0_OR_GREATER + ArgumentOutOfRangeException.ThrowIfNotEqual(value, other, paramName); +#else + if (!EqualityComparer.Default.Equals(value, other)) + { + ThrowArgumentOutOfRangeException( + paramName, + value, + $"{paramName} ('{value}') must be equal to '{other}'." + ); + } +#endif + } +} diff --git a/src/NetEvolve.Arguments/Argument_ThrowIfNull.cs b/src/NetEvolve.Arguments/Argument_ThrowIfNull.cs index 0e7b4e1..59e5aad 100644 --- a/src/NetEvolve.Arguments/Argument_ThrowIfNull.cs +++ b/src/NetEvolve.Arguments/Argument_ThrowIfNull.cs @@ -29,6 +29,31 @@ public static void ThrowIfNull( { ThrowArgumentNullException(paramName); } +#endif + } + + /// Throws an if is null. + /// The reference type argument to validate as non-null. + /// The name of the parameter with which corresponds. + [DebuggerStepThrough] + [StackTraceHidden] +#if NET7_0_OR_GREATER + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#else + [MethodImpl(MethodImplOptions.NoInlining)] +#endif + public static unsafe void ThrowIfNull( + [NotNull] void* argument, + [CallerArgumentExpression(nameof(argument))] string? paramName = null + ) + { +#if NET7_0_OR_GREATER + ArgumentNullException.ThrowIfNull(argument, paramName); +#else + if (argument == null) + { + ThrowArgumentNullException(paramName); + } #endif } } diff --git a/tests/NetEvolve.Arguments.Tests.Unit/ArgumentTests_ThrowIfEqual.cs b/tests/NetEvolve.Arguments.Tests.Unit/ArgumentTests_ThrowIfEqual.cs new file mode 100644 index 0000000..e91e1d9 --- /dev/null +++ b/tests/NetEvolve.Arguments.Tests.Unit/ArgumentTests_ThrowIfEqual.cs @@ -0,0 +1,35 @@ +namespace NetEvolve.Arguments.Tests.Unit; + +using System; +using Xunit; + +public sealed partial class ArgumentTests +{ + [Fact] + public void ThrowIfEqual_WhenArgumentIsEqualToMaximum_ThrowsArgumentOutOfRangeException() + { + // Arrange + var argument = 1; + var maximum = 1; + + // Act + void Act() => Argument.ThrowIfEqual(argument, maximum); + + // Assert + _ = Assert.Throws("argument", Act); + } + + [Fact] + public void ThrowIfEqual_WhenArgumentIsNotEqualToMaximum_ReturnsArgument() + { + // Arrange + var argument = 2; + var maximum = 1; + + // Act + Argument.ThrowIfEqual(argument, maximum); + + // Assert + Assert.True(true); + } +} diff --git a/tests/NetEvolve.Arguments.Tests.Unit/ArgumentTests_ThrowIfNotEqual.cs b/tests/NetEvolve.Arguments.Tests.Unit/ArgumentTests_ThrowIfNotEqual.cs new file mode 100644 index 0000000..b7a201e --- /dev/null +++ b/tests/NetEvolve.Arguments.Tests.Unit/ArgumentTests_ThrowIfNotEqual.cs @@ -0,0 +1,35 @@ +namespace NetEvolve.Arguments.Tests.Unit; + +using System; +using Xunit; + +public sealed partial class ArgumentTests +{ + [Fact] + public void ThrowIfNotEqual_WhenArgumentIsNotEqualToMaximum_ThrowsArgumentOutOfRangeException() + { + // Arrange + var argument = 2; + var maximum = 1; + + // Act + void Act() => Argument.ThrowIfNotEqual(argument, maximum); + + // Assert + _ = Assert.Throws("argument", Act); + } + + [Fact] + public void ThrowIfNotEqual_WhenArgumentIsEqualToMaximum_ReturnsArgument() + { + // Arrange + var argument = 1; + var maximum = 1; + + // Act + Argument.ThrowIfNotEqual(argument, maximum); + + // Assert + Assert.True(true); + } +} diff --git a/tests/NetEvolve.Arguments.Tests.Unit/ArgumentTests_ThrowIfNull.cs b/tests/NetEvolve.Arguments.Tests.Unit/ArgumentTests_ThrowIfNull.cs index 9639b91..d99ab27 100644 --- a/tests/NetEvolve.Arguments.Tests.Unit/ArgumentTests_ThrowIfNull.cs +++ b/tests/NetEvolve.Arguments.Tests.Unit/ArgumentTests_ThrowIfNull.cs @@ -30,4 +30,30 @@ public void ThrowIfNull_WhenArgumentIsNotEmpty_ReturnsArgument() // Assert Assert.True(true); } + + [Fact] + public unsafe void ThrowIfNull_WhenArgumentIsNullPointer_ThrowsArgumentNullException() + { + // Arrange + int* argument = null; + + // Act + void Act() => Argument.ThrowIfNull(argument); + + // Assert + _ = Assert.Throws("argument", Act); + } + + [Fact] + public unsafe void ThrowIfNull_WhenArgumentIsNotNullPointer_ReturnsArgument() + { + // Arrange + var argument = (int*)0x1; + + // Act + Argument.ThrowIfNull(argument); + + // Assert + Assert.True(true); + } } diff --git a/tests/NetEvolve.Arguments.Tests.Unit/NetEvolve.Arguments.Tests.Unit.csproj b/tests/NetEvolve.Arguments.Tests.Unit/NetEvolve.Arguments.Tests.Unit.csproj index 3980420..1c3ff12 100644 --- a/tests/NetEvolve.Arguments.Tests.Unit/NetEvolve.Arguments.Tests.Unit.csproj +++ b/tests/NetEvolve.Arguments.Tests.Unit/NetEvolve.Arguments.Tests.Unit.csproj @@ -5,6 +5,8 @@ true $(NoWarn);NU1701 + + true