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

Revert: breaking changes (compared to 2.0.1) #130

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,6 @@ dotnet_diagnostic.SA1642.severity = none

# SA1516: Elements should be separated by blank line
dotnet_diagnostic.SA1516.severity = none

[*.csproj]
indent_size = 2
131 changes: 99 additions & 32 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,123 @@

All notable changes to this project are documented in this file.

## [1.10.0] - 2024-02-14
## [2.1.0-alpha.0] - to be released

### Added

- `ErrorType.Forbidden`
- README to NuGet package
- [#94](https://github.com/amantinband/error-or/issues/94), [#95](https://github.com/amantinband/error-or/pull/95) Added missing async versions of `FailIf` methods

## [1.9.0] - 2024-01-06
```cs
public async Task<ErrorOr<TValue>> FailIfAsync(Func<TValue, Task<bool>> onValue, Error error)
```

### Added
```cs
public static async Task<ErrorOr<TValue>> FailIf<TValue>(
this Task<ErrorOr<TValue>> errorOr,
Func<TValue, bool> onValue,
Error error)
```

- `ToErrorOr`
```cs
public static async Task<ErrorOr<TValue>> FailIfAsync<TValue>(
this Task<ErrorOr<TValue>> errorOr,
Func<TValue, Task<bool>> onValue,
Error error)
```

## [2.0.0] - 2024-03-26
- [#104](https://github.com/amantinband/error-or/pull/104) Support for .NET 8 was added

### Added
- [#109](https://github.com/amantinband/error-or/issues/109), [#111](https://github.com/amantinband/error-or/pull/111) Added `FailIf` method overloads that allow to use value in error definition using `Func<TValue, Error>` error builder

- `FailIf`
```cs
public ErrorOr<TValue> FailIf(Func<TValue, bool> onValue, Func<TValue, Error> errorBuilder)
```

```cs
public async Task<ErrorOr<TValue>> FailIfAsync(Func<TValue, Task<bool>> onValue, Func<TValue, Task<Error>> errorBuilder)
```

```csharp
public ErrorOr<TValue> FailIf(Func<TValue, bool> onValue, Error error)
```
```cs
public static async Task<ErrorOr<TValue>> FailIf<TValue>(
this Task<ErrorOr<TValue>> errorOr,
Func<TValue, bool> onValue,
Func<TValue, Error> errorBuilder)
```

```csharp
ErrorOr<int> errorOr = 1;
errorOr.FailIf(x => x > 0, Error.Failure());
```
```cs
public static async Task<ErrorOr<TValue>> FailIfAsync<TValue>(
this Task<ErrorOr<TValue>> errorOr,
Func<TValue, Task<bool>> onValue,
Func<TValue, Task<Error>> errorBuilder)
```

Value can now be used to build the error:

```cs
ErrorOr<int> result = errorOrInt
.FailIf(num => num > 3, (num) => Error.Failure(description: $"{num} is greater than 3"));
```

### Fixed

- [#85](https://github.com/amantinband/error-or/issues/85), [#97](https://github.com/amantinband/error-or/pull/97) `ErrorOr` turned into Value Object by reimplementing `Equals` and `GetHashCode` methods

New dependency was introduced to [Microsoft.Bcl.HashCode](https://www.nuget.org/packages/Microsoft.Bcl.HashCode) and development dependency was introduced to [Nullable](https://www.nuget.org/packages/Nullable)

### Optimized

- [#98](https://github.com/amantinband/error-or/issues/98), [#99](https://github.com/amantinband/error-or/pull/99) Memory consumption optimized by moving static empty errors lists from generic struct into non-generic class

## [2.0.1] - 2024-03-26

### Breaking Changes

- `Then` that receives an action is now called `ThenDo`

```diff
-public ErrorOr<TValue> Then(Action<TValue> action)
+public ErrorOr<TValue> ThenDo(Action<TValue> action)
```
```diff
-public ErrorOr<TValue> Then(Action<TValue> action)
+public ErrorOr<TValue> ThenDo(Action<TValue> action)
```

```diff
-public static async Task<ErrorOr<TValue>> Then<TValue>(this Task<ErrorOr<TValue>> errorOr, Action<TValue> action)
+public static async Task<ErrorOr<TValue>> ThenDo<TValue>(this Task<ErrorOr<TValue>> errorOr, Action<TValue> action)
```
```diff
-public static async Task<ErrorOr<TValue>> Then<TValue>(this Task<ErrorOr<TValue>> errorOr, Action<TValue> action)
+public static async Task<ErrorOr<TValue>> ThenDo<TValue>(this Task<ErrorOr<TValue>> errorOr, Action<TValue> action)
```

- `ThenAsync` that receives an action is now called `ThenDoAsync`

```diff
-public async Task<ErrorOr<TValue>> ThenAsync(Func<TValue, Task> action)
+public async Task<ErrorOr<TValue>> ThenDoAsync(Func<TValue, Task> action)
```
```diff
-public async Task<ErrorOr<TValue>> ThenAsync(Func<TValue, Task> action)
+public async Task<ErrorOr<TValue>> ThenDoAsync(Func<TValue, Task> action)
```

```diff
-public static async Task<ErrorOr<TValue>> ThenAsync<TValue>(this Task<ErrorOr<TValue>> errorOr, Func<TValue, Task> action)
+public static async Task<ErrorOr<TValue>> ThenDoAsync<TValue>(this Task<ErrorOr<TValue>> errorOr, Func<TValue, Task> action)
```

```diff
-public static async Task<ErrorOr<TValue>> ThenAsync<TValue>(this Task<ErrorOr<TValue>> errorOr, Func<TValue, Task> action)
+public static async Task<ErrorOr<TValue>> ThenDoAsync<TValue>(this Task<ErrorOr<TValue>> errorOr, Func<TValue, Task> action)
```
### Added

- `FailIf`

```csharp
public ErrorOr<TValue> FailIf(Func<TValue, bool> onValue, Error error)
```

```csharp
ErrorOr<int> errorOr = 1;
errorOr.FailIf(x => x > 0, Error.Failure());
```

## [1.10.0] - 2024-02-14

### Added

- `ErrorType.Forbidden`
- README to NuGet package

## [1.9.0] - 2024-01-06

### Added

- `ToErrorOr`
5 changes: 3 additions & 2 deletions src/ErrorOr.csproj
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0;net6.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup>
<PackageId>ErrorOr</PackageId>
<Version>2.0.1</Version>
<VersionPrefix>2.1.0</VersionPrefix>
<VersionSuffix>alpha.0</VersionSuffix>
<Authors>Amichai Mantinband</Authors>
<PackageIcon>icon-square.png</PackageIcon>
<PackageTags>Result,Results,ErrorOr,Error,Handling</PackageTags>
Expand Down
6 changes: 0 additions & 6 deletions src/ErrorOr/EmptyErrors.cs

This file was deleted.

31 changes: 4 additions & 27 deletions src/ErrorOr/ErrorOr.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,6 @@ namespace ErrorOr;
private readonly TValue? _value = default;
private readonly List<Error>? _errors = null;

/// <summary>
/// Prevents a default <see cref="ErrorOr"/> struct from being created.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when this method is called.</exception>
public ErrorOr()
{
throw new InvalidOperationException("Default construction of ErrorOr<TValue> is invalid. Please use provided factory methods to instantiate.");
}

private ErrorOr(Error error)
{
_errors = [error];
Expand Down Expand Up @@ -62,42 +53,28 @@ private ErrorOr(TValue value)
/// <summary>
/// Gets the list of errors. If the state is not error, the list will contain a single error representing the state.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when no errors are present.</exception>
public List<Error> Errors => IsError ? _errors : throw new InvalidOperationException("The Errors property cannot be accessed when no errors have been recorded. Check IsError before accessing Errors.");
public List<Error> Errors => IsError ? _errors : KnownErrors.CachedNoErrorsList;

/// <summary>
/// Gets the list of errors. If the state is not error, the list will be empty.
/// </summary>
public List<Error> ErrorsOrEmptyList => IsError ? _errors : EmptyErrors.Instance;
public List<Error> ErrorsOrEmptyList => IsError ? _errors : KnownErrors.CachedEmptyErrorsList;

/// <summary>
/// Gets the value.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when no value is present.</exception>
public TValue Value
{
get
{
if (IsError)
{
throw new InvalidOperationException("The Value property cannot be accessed when errors have been recorded. Check IsError before accessing Value.");
}

return _value;
}
}
public TValue Value => _value!;

/// <summary>
/// Gets the first error.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when no errors are present.</exception>
public Error FirstError
{
get
{
if (!IsError)
{
throw new InvalidOperationException("The FirstError property cannot be accessed when no errors have been recorded. Check IsError before accessing FirstError.");
return KnownErrors.NoFirstError;
}

return _errors[0];
Expand Down
16 changes: 16 additions & 0 deletions src/Errors/KnownErrors.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace ErrorOr;

internal static class KnownErrors
{
public static Error NoFirstError { get; } = Error.Unexpected(
code: "ErrorOr.NoFirstError",
description: "First error cannot be retrieved from a successful ErrorOr.");

public static Error NoErrors { get; } = Error.Unexpected(
code: "ErrorOr.NoErrors",
description: "Error list cannot be retrieved from a successful ErrorOr.");

public static List<Error> CachedNoErrorsList { get; } = new (1) { NoErrors };

public static List<Error> CachedEmptyErrorsList { get; } = new (0);
}
Loading