Skip to content
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

Exceptions for invalid use - review and extensions #106

Prev Previous commit
Next Next commit
feat: add additional null checks to implicit conversions
When clients have <Nullable> turned off, the C# compiler won't hint that null shouldn't be passed as the errors array/list. By explicitly checking for null, we eliminate these error cases.

Signed-off-by: Kenny Pflug <kenny.pflug@live.de>
  • Loading branch information
feO2x committed May 9, 2024
commit 73be4f798e08b56f57862cb58e915e0e036a8c3a
102 changes: 56 additions & 46 deletions src/ErrorOr/ErrorOr.ImplicitConverters.cs
Original file line number Diff line number Diff line change
@@ -1,46 +1,56 @@
namespace ErrorOr;

public readonly partial record struct ErrorOr<TValue> : IErrorOr<TValue>
{
/// <summary>
/// Creates an <see cref="ErrorOr{TValue}"/> from a value.
/// </summary>
public static implicit operator ErrorOr<TValue>(TValue value)
{
return new ErrorOr<TValue>(value);
}

/// <summary>
/// Creates an <see cref="ErrorOr{TValue}"/> from an error.
/// </summary>
public static implicit operator ErrorOr<TValue>(Error error)
{
return new ErrorOr<TValue>(error);
}

/// <summary>
/// Creates an <see cref="ErrorOr{TValue}"/> from a list of errors.
/// </summary>
public static implicit operator ErrorOr<TValue>(List<Error> errors)
{
if (errors.Count == 0)
{
throw new InvalidOperationException("Cannot create an ErrorOr<TValue> from an empty list of errors. Provide at least one error.");
}

return new ErrorOr<TValue>(errors);
}

/// <summary>
/// Creates an <see cref="ErrorOr{TValue}"/> from a list of errors.
/// </summary>
public static implicit operator ErrorOr<TValue>(Error[] errors)
{
if (errors.Length == 0)
{
throw new InvalidOperationException("Cannot create an ErrorOr<TValue> from an empty array of errors. Provide at least one error.");
}

return new ErrorOr<TValue>(errors.ToList());
}
}
namespace ErrorOr;

public readonly partial record struct ErrorOr<TValue> : IErrorOr<TValue>
{
/// <summary>
/// Creates an <see cref="ErrorOr{TValue}"/> from a value.
/// </summary>
public static implicit operator ErrorOr<TValue>(TValue value)
{
return new ErrorOr<TValue>(value);
}

/// <summary>
/// Creates an <see cref="ErrorOr{TValue}"/> from an error.
/// </summary>
public static implicit operator ErrorOr<TValue>(Error error)
{
return new ErrorOr<TValue>(error);
}

/// <summary>
/// Creates an <see cref="ErrorOr{TValue}"/> from a list of errors.
/// </summary>
public static implicit operator ErrorOr<TValue>(List<Error> errors)
{
if (errors is null)
{
throw new ArgumentNullException(nameof(errors));
}

if (errors.Count == 0)
{
throw new InvalidOperationException("Cannot create an ErrorOr<TValue> from an empty list of errors. Provide at least one error.");
}

return new ErrorOr<TValue>(errors);
}

/// <summary>
/// Creates an <see cref="ErrorOr{TValue}"/> from a list of errors.
/// </summary>
public static implicit operator ErrorOr<TValue>(Error[] errors)
{
if (errors is null)
{
throw new ArgumentNullException(nameof(errors));
}

if (errors.Length == 0)
{
throw new InvalidOperationException("Cannot create an ErrorOr<TValue> from an empty array of errors. Provide at least one error.");
}

return new ErrorOr<TValue>(errors.ToList());
}
}
18 changes: 18 additions & 0 deletions tests/ErrorOr/ErrorOr.InstantiationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -376,4 +376,22 @@ public void CreateErrorOr_WhenEmptyErrorsArray_ShouldThrow()
// Assert
errorOrInt.Should().ThrowExactly<InvalidOperationException>();
}

[Fact]
public void CreateErrorOr_WhenNullIsPassedAsErrorsList_ShouldThrowArgumentNullException()
{
Func<ErrorOr<int>> act = () => default(List<Error>)!;

act.Should().ThrowExactly<ArgumentNullException>()
.And.ParamName.Should().Be("errors");
}

[Fact]
public void CreateErrorOr_WhenNullIsPassedAsErrorsArray_ShouldThrowArgumentNullException()
{
Func<ErrorOr<int>> act = () => default(Error[])!;

act.Should().ThrowExactly<ArgumentNullException>()
.And.ParamName.Should().Be("errors");
}
}