Skip to content

Commit

Permalink
Make type parameter T of the Null() method nullable and add overload …
Browse files Browse the repository at this point in the history
…for value types. (#261)

* Add nullable annotation "?" to T of Null() to supress null warnings on returned value.

* Add overload of Null() with generic constraint for value types to allow assignment of return value to non-nullable value types when passed a nullable value type.

* Add unit tests to ensure that Null() returns a non-nullable value type when passed a nullable value type

* Update GuardClauses.csproj

* Update GuardClauses.UnitTests.csproj

* Revert "Update to dotnet 7.0"

---------

Co-authored-by: amalkrishna <[email protected]>
Co-authored-by: Steve Smith <[email protected]>
  • Loading branch information
3 people committed Jul 31, 2023
1 parent f26fb99 commit e6388c9
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 4 deletions.
41 changes: 37 additions & 4 deletions src/GuardClauses/GuardAgainstNullExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ public static partial class GuardClauseExtensions
/// <returns><paramref name="input" /> if the value is not null.</returns>
#if NETSTANDARD || NETFRAMEWORK
public static T Null<T>(this IGuardClause guardClause,
[NotNull][ValidatedNotNull] T input,
[NotNull][ValidatedNotNull] T? input,
string parameterName,
string? message = null)
#else
public static T Null<T>(this IGuardClause guardClause,
[NotNull][ValidatedNotNull]T input,
[NotNull][ValidatedNotNull]T? input,
[CallerArgumentExpression("input")] string? parameterName = null,
string? message = null)
#endif
Expand All @@ -47,6 +47,39 @@ public static T Null<T>(this IGuardClause guardClause,
return input;
}

/// <summary>
/// Throws an <see cref="ArgumentNullException" /> if <paramref name="input" /> is null.
/// </summary>
/// <typeparam name="T">Must be a value type.</typeparam>
/// <param name="guardClause"></param>
/// <param name="input"></param>
/// <param name="parameterName"></param>
/// <param name="message">Optional. Custom error message</param>
/// <returns><paramref name="input" /> if the value is not null.</returns>
#if NETSTANDARD || NETFRAMEWORK
public static T Null<T>(this IGuardClause guardClause,
[NotNull][ValidatedNotNull] T? input,
string parameterName,
string? message = null) where T : struct
#else
public static T Null<T>(this IGuardClause guardClause,
[NotNull][ValidatedNotNull]T? input,
[CallerArgumentExpression("input")] string? parameterName = null,
string? message = null) where T : struct
#endif
{
if (input is null)
{
if (string.IsNullOrEmpty(message))
{
throw new ArgumentNullException(parameterName);
}
throw new ArgumentNullException(parameterName, message);
}

return input.Value;
}

/// <summary>
/// Throws an <see cref="ArgumentNullException" /> if <paramref name="input" /> is null.
/// Throws an <see cref="ArgumentException" /> if <paramref name="input" /> is an empty string.
Expand Down Expand Up @@ -220,13 +253,13 @@ public static T Default<T>(this IGuardClause guardClause,
/// <exception cref="ArgumentNullException"></exception>
#if NETSTANDARD || NETFRAMEWORK
public static T NullOrInvalidInput<T>(this IGuardClause guardClause,
T input,
[NotNull] T? input,
string parameterName,
Func<T, bool> predicate,
string? message = null)
#else
public static T NullOrInvalidInput<T>(this IGuardClause guardClause,
T input,
[NotNull] T? input,
string parameterName,
Func<T, bool> predicate,
string? message = null)
Expand Down
35 changes: 35 additions & 0 deletions test/GuardClauses.UnitTests/GuardAgainstNull.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,41 @@ public void ReturnsExpectedValueWhenGivenNonNullValue()
Assert.Equal(obj, Guard.Against.Null(obj, "object"));
}

[Fact]
public void ReturnsNonNullableValueTypeWhenGivenNullableValueTypeIsNotNull()
{
int? @int = 4;
Assert.False(IsNullableType(Guard.Against.Null(@int, "int")));

double? @double = 11.11;
Assert.False(IsNullableType(Guard.Against.Null(@double, "@double")));

DateTime? now = DateTime.Now;
Assert.False(IsNullableType(Guard.Against.Null(now, "now")));

Guid? guid = Guid.Empty;
Assert.False(IsNullableType(Guard.Against.Null(guid, "guid")));

static bool IsNullableType<T>(T value)
{
if (value is null)
{
return false;
}
Type type = typeof(T);
if (!type.IsValueType)
{
return true;
}
if (Nullable.GetUnderlyingType(type) != null)
{
return true;
}
return false;

}
}

[Theory]
[InlineData(null, "Value cannot be null. (Parameter 'parameterName')")]
[InlineData("Please provide correct value", "Please provide correct value (Parameter 'parameterName')")]
Expand Down

0 comments on commit e6388c9

Please sign in to comment.