Skip to content

Commit

Permalink
chore: Added methods ThrowIfEqual and ThrowIfNotEqual (#128)
Browse files Browse the repository at this point in the history
* chore: Added methods `ThrowIfEqual` and `ThrowIfNotEqual`

* docs: Updated README

* chore(tests): Tests for newly introduced methods added

* chore(tests): Tests for newly introduced method `ThrowIfNull(void*, string?)` added

* docs: Updated README
  • Loading branch information
samtrion authored Apr 5, 2024
1 parent 8b3be74 commit d365062
Show file tree
Hide file tree
Showing 15 changed files with 259 additions and 25 deletions.
37 changes: 23 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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, T, String)`](https://learn.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception.throwifgreaterthan), which was introduced with .NET 8
### `Argument.ThrowIfEqual<T>(T, T, string?)`
Throws an `ArgumentOutOfRangeException` if the first argument is equal to the second argument. Inplace replacement for [`ArgumentOutOfRangeException.ThrowIfEqual<T>(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, 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, T, string?)`
Throws an `ArgumentOutOfRangeException` if the first argument is greater than the second argument. Inplace replacement for [`ArgumentOutOfRangeException.ThrowIfGreaterThan<T>(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, 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, 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, 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, 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, T, string?)`
Throws an `ArgumentOutOfRangeException` if the first argument is less than the second argument. Inplace replacement for [`ArgumentOutOfRangeException.ThrowIfLessThan<T>(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, 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, 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, T, string?)`
Throws an `ArgumentOutOfRangeException` if the first argument is not equal to the second argument. Inplace replacement for [`ArgumentOutOfRangeException.ThrowIfNotEqual<T>(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**.
4 changes: 2 additions & 2 deletions src/NetEvolve.Arguments/Argument_ThrowArgumentException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@ public static partial class Argument
[DoesNotReturn]
[MethodImpl(MethodImplOptions.NoInlining)]
[StackTraceHidden]
private static void ThrowArgumentOutOfRangeException<T>(string? paramName, T value)
where T : IComparable<T>
private static void ThrowArgumentOutOfRangeException<T>(
string? paramName,
T value,
string? message = null
)
{
throw new ArgumentOutOfRangeException(paramName, value, null);
throw new ArgumentOutOfRangeException(paramName, value, message);
}
}
#endif
41 changes: 41 additions & 0 deletions src/NetEvolve.Arguments/Argument_ThrowIfEqual.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>Throws an <see cref="ArgumentOutOfRangeException"/> if <paramref name="value"/> is equal to <paramref name="other"/>.</summary>
/// <param name="value">The argument to validate as not equal to <paramref name="other"/>.</param>
/// <param name="other">The value to compare with <paramref name="value"/>.</param>
/// <param name="paramName">The name of the parameter with which <paramref name="value"/> corresponds.</param>
[DebuggerStepThrough]
[StackTraceHidden]
#if NET8_0_OR_GREATER
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[MethodImpl(MethodImplOptions.NoInlining)]
#endif
public static void ThrowIfEqual<T>(
T value,
T other,
[CallerArgumentExpression(nameof(value))] string? paramName = null
)
where T : IEquatable<T>
{
#if NET8_0_OR_GREATER
ArgumentOutOfRangeException.ThrowIfEqual(value, other, paramName);
#else
if (EqualityComparer<T>.Default.Equals(value, other))
{
ThrowArgumentOutOfRangeException(
paramName,
value,
$"{paramName} ('{value}') must not be equal to '{other}'."
);
}
#endif
}
}
7 changes: 6 additions & 1 deletion src/NetEvolve.Arguments/Argument_ThrowIfGreaterThan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -30,7 +31,11 @@ public static void ThrowIfGreaterThan<T>(
#else
if (value.CompareTo(other) > 0)
{
ThrowArgumentOutOfRangeException(paramName, value);
ThrowArgumentOutOfRangeException(
paramName,
value,
$"{paramName} ('{value}') must be less than or equal to '{other}'."
);
}
#endif
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ public static void ThrowIfGreaterThanOrEqual<T>(
#else
if (value.CompareTo(other) >= 0)
{
ThrowArgumentOutOfRangeException(paramName, value);
ThrowArgumentOutOfRangeException(
paramName,
value,
$"{paramName} ('{value}') must be less than '{other}'."
);
}
#endif
}
Expand Down
6 changes: 5 additions & 1 deletion src/NetEvolve.Arguments/Argument_ThrowIfLessThan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ public static void ThrowIfLessThan<T>(
#else
if (value.CompareTo(other) < 0)
{
ThrowArgumentOutOfRangeException(paramName, value);
ThrowArgumentOutOfRangeException(
paramName,
value,
$"{paramName} ('{value}') must be greater than '{other}'."
);
}
#endif
}
Expand Down
6 changes: 5 additions & 1 deletion src/NetEvolve.Arguments/Argument_ThrowIfLessThanOrEqual.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ public static void ThrowIfLessThanOrEqual<T>(
#else
if (value.CompareTo(other) <= 0)
{
ThrowArgumentOutOfRangeException(paramName, value);
ThrowArgumentOutOfRangeException(
paramName,
value,
$"{paramName} ('{value}') must be greater than or equal to '{other}'."
);
}
#endif
}
Expand Down
41 changes: 41 additions & 0 deletions src/NetEvolve.Arguments/Argument_ThrowIfNotEqual.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>Throws an <see cref="ArgumentOutOfRangeException"/> if <paramref name="value"/> is not equal to <paramref name="other"/>.</summary>
/// <param name="value">The argument to validate as equal to <paramref name="other"/>.</param>
/// <param name="other">The value to compare with <paramref name="value"/>.</param>
/// <param name="paramName">The name of the parameter with which <paramref name="value"/> corresponds.</param>
[DebuggerStepThrough]
[StackTraceHidden]
#if NET8_0_OR_GREATER
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[MethodImpl(MethodImplOptions.NoInlining)]
#endif
public static void ThrowIfNotEqual<T>(
T value,
T other,
[CallerArgumentExpression(nameof(value))] string? paramName = null
)
where T : IEquatable<T>
{
#if NET8_0_OR_GREATER
ArgumentOutOfRangeException.ThrowIfNotEqual(value, other, paramName);
#else
if (!EqualityComparer<T>.Default.Equals(value, other))
{
ThrowArgumentOutOfRangeException(
paramName,
value,
$"{paramName} ('{value}') must be equal to '{other}'."
);
}
#endif
}
}
25 changes: 25 additions & 0 deletions src/NetEvolve.Arguments/Argument_ThrowIfNull.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,31 @@ public static void ThrowIfNull(
{
ThrowArgumentNullException(paramName);
}
#endif
}

/// <summary>Throws an <see cref="ArgumentNullException"/> if <paramref name="argument"/> is null.</summary>
/// <param name="argument">The reference type argument to validate as non-null.</param>
/// <param name="paramName">The name of the parameter with which <paramref name="argument"/> corresponds.</param>
[DebuggerStepThrough]
[StackTraceHidden]
#if NET7_0_OR_GREATER
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[MethodImpl(MethodImplOptions.NoInlining)]
#endif
public static unsafe void ThrowIfNull(

Check warning on line 45 in src/NetEvolve.Arguments/Argument_ThrowIfNull.cs

View workflow job for this annotation

GitHub Actions / Build & Tests / Tests / Testing .NET solution (none)

Make sure that using "unsafe" is safe here. (https://rules.sonarsource.com/csharp/RSPEC-6640)

Check warning on line 45 in src/NetEvolve.Arguments/Argument_ThrowIfNull.cs

View workflow job for this annotation

GitHub Actions / Build & Tests / Tests / Testing .NET solution (none)

Make sure that using "unsafe" is safe here. (https://rules.sonarsource.com/csharp/RSPEC-6640)

Check warning on line 45 in src/NetEvolve.Arguments/Argument_ThrowIfNull.cs

View workflow job for this annotation

GitHub Actions / Build & Tests / Tests / Testing .NET solution (none)

Make sure that using "unsafe" is safe here. (https://rules.sonarsource.com/csharp/RSPEC-6640)

Check warning on line 45 in src/NetEvolve.Arguments/Argument_ThrowIfNull.cs

View workflow job for this annotation

GitHub Actions / Build & Tests / Tests / Testing .NET solution (none)

Make sure that using "unsafe" is safe here. (https://rules.sonarsource.com/csharp/RSPEC-6640)

Check warning on line 45 in src/NetEvolve.Arguments/Argument_ThrowIfNull.cs

View workflow job for this annotation

GitHub Actions / Build & Tests / Tests / Testing .NET solution (none)

Make sure that using "unsafe" is safe here. (https://rules.sonarsource.com/csharp/RSPEC-6640)

Check warning on line 45 in src/NetEvolve.Arguments/Argument_ThrowIfNull.cs

View workflow job for this annotation

GitHub Actions / Build & Tests / Tests / Testing .NET solution (none)

Make sure that using "unsafe" is safe here. (https://rules.sonarsource.com/csharp/RSPEC-6640)

Check warning on line 45 in src/NetEvolve.Arguments/Argument_ThrowIfNull.cs

View workflow job for this annotation

GitHub Actions / Build & Tests / Tests / Testing .NET solution (none)

Make sure that using "unsafe" is safe here. (https://rules.sonarsource.com/csharp/RSPEC-6640)

Check warning on line 45 in src/NetEvolve.Arguments/Argument_ThrowIfNull.cs

View workflow job for this annotation

GitHub Actions / Build & Tests / Tests / Testing .NET solution (none)

Make sure that using "unsafe" is safe here. (https://rules.sonarsource.com/csharp/RSPEC-6640)

Check warning on line 45 in src/NetEvolve.Arguments/Argument_ThrowIfNull.cs

View workflow job for this annotation

GitHub Actions / Build & Tests / Tests / Testing .NET solution (none)

Make sure that using "unsafe" is safe here. (https://rules.sonarsource.com/csharp/RSPEC-6640)

Check warning on line 45 in src/NetEvolve.Arguments/Argument_ThrowIfNull.cs

View workflow job for this annotation

GitHub Actions / Build & Tests / Tests / Testing .NET solution (none)

Make sure that using "unsafe" is safe here. (https://rules.sonarsource.com/csharp/RSPEC-6640)
[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
}
}
35 changes: 35 additions & 0 deletions tests/NetEvolve.Arguments.Tests.Unit/ArgumentTests_ThrowIfEqual.cs
Original file line number Diff line number Diff line change
@@ -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<ArgumentOutOfRangeException>("argument", Act);
}

[Fact]
public void ThrowIfEqual_WhenArgumentIsNotEqualToMaximum_ReturnsArgument()
{
// Arrange
var argument = 2;
var maximum = 1;

// Act
Argument.ThrowIfEqual(argument, maximum);

// Assert
Assert.True(true);
}
}
Original file line number Diff line number Diff line change
@@ -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<ArgumentOutOfRangeException>("argument", Act);
}

[Fact]
public void ThrowIfNotEqual_WhenArgumentIsEqualToMaximum_ReturnsArgument()
{
// Arrange
var argument = 1;
var maximum = 1;

// Act
Argument.ThrowIfNotEqual(argument, maximum);

// Assert
Assert.True(true);
}
}
26 changes: 26 additions & 0 deletions tests/NetEvolve.Arguments.Tests.Unit/ArgumentTests_ThrowIfNull.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ArgumentNullException>("argument", Act);
}

[Fact]
public unsafe void ThrowIfNull_WhenArgumentIsNotNullPointer_ReturnsArgument()
{
// Arrange
var argument = (int*)0x1;

// Act
Argument.ThrowIfNull(argument);

// Assert
Assert.True(true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>

<NoWarn>$(NoWarn);NU1701</NoWarn>

<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
Expand Down

0 comments on commit d365062

Please sign in to comment.