Skip to content
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
79 changes: 79 additions & 0 deletions OperationResult.Tests/ResultTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using static OperationResult.Helpers;

namespace OperationResult.Tests
Expand Down Expand Up @@ -208,5 +209,83 @@ public void TestResultWithMultipleErrorsImplicitToBool()
isSuccess = GetResultOrMultipleErrors(4);
Assert.IsFalse(isSuccess);
}

[TestMethod]
public void TestResultEquals()
{
Result<int, string> r = Ok(1);
var tests = new List<(bool, Result<int, string>)>()
{
(true, Ok(1)),
(false, Ok(2)),
(false, Ok(0)),
(false, Error("")),
(false, Error<string>(null)),
};
foreach (var (w, result) in tests)
{
Assert.AreEqual(w, r == result);
}

r = Error("E");
tests = new List<(bool, Result<int, string>)>()
{
(false, Error("")),
(false, Error<string>(null)),
(true, Error("E")),
(false, Ok(1)),
(false, Ok(0)),
};
foreach (var (w, result) in tests)
{
Assert.AreEqual(w, r == result);
}

r = Error<string>(null);
tests = new List<(bool, Result<int, string>)>()
{
(false, Error("")),
(true, Error<string>(null)),
(false, Error("E")),
(false, Ok(1)),
(false, Ok(0)),
};
foreach (var (w, result) in tests)
{
Assert.AreEqual(w, r == result);
}
}

[TestMethod]
public void TestResultEquals2()
{
Result<string, string> r = Ok("1");
var tests = new List<(bool, Result<string, string>)>()
{
(true, Ok("1")),
(false, Ok("2")),
(false, Ok<string>(null)),
(false, Error("")),
(false, Error<string>(null)),
};
foreach (var (w, result) in tests)
{
Assert.AreEqual(w, r == result);
}

r = Ok<string>(null);
tests = new List<(bool, Result<string, string>)>()
{
(false, Ok("1")),
(false, Ok("2")),
(true, Ok<string>(null)),
(false, Error("")),
(false, Error<string>(null)),
};
foreach (var (w, result) in tests)
{
Assert.AreEqual(w, r == result);
}
}
}
}
21 changes: 21 additions & 0 deletions OperationResult/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,26 @@ public static ErrorTag<TError> Error<TError>(TError error)
{
return new ErrorTag<TError>(error);
}

internal static bool Equals<V1, V2>((bool, V1, V2) r1, (bool, V1, V2) r2)
{
if (r1.Item1 != r2.Item1)
{
return false;
}
if (r1.Item1)
{
if (r1.Item2 == null)
{
return r2.Item2 == null;
}
return r1.Item2.Equals(r2.Item2);
}
if (r1.Item3 == null)
{
return r2.Item3 == null;
}
return r1.Item3.Equals(r2.Item3);
}
}
}
131 changes: 124 additions & 7 deletions OperationResult/Result.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using OperationResult.Tags;

using System;
using OperationResult.Tags;

namespace OperationResult
{
/// <summary>
/// Result of operation (without Error field)
/// </summary>
/// <typeparam name="TResult">Type of Value field</typeparam>
public struct Result<TResult>
public struct Result<TResult> : IEquatable<Result<TResult>>
{
private readonly bool _isSuccess;

Expand Down Expand Up @@ -47,15 +48,44 @@ public static implicit operator Result<TResult>(SuccessTag<TResult> tag)
public static implicit operator Result<TResult>(ErrorTag tag)
{
return ErrorResult;
}
}

public static bool operator ==(Result<TResult> r1, Result<TResult> r2)
{
return Helpers.Equals((r1._isSuccess, r1.Value, 1), (r2._isSuccess, r2.Value, 1));
}

public static bool operator !=(Result<TResult> r1, Result<TResult> r2)
{
return !(r1 == r2);
}

public override int GetHashCode()
{
return this.IsSuccess ? this.Value.GetHashCode() : this.IsSuccess.GetHashCode();
}

public override bool Equals(object obj)
{
if (obj is Result<TResult> t)
{
return this == t;
}
return false;
}

public bool Equals(Result<TResult> other)
{
return this == other;
}
}

/// <summary>
/// Result of operation (with Error field)
/// </summary>
/// <typeparam name="TResult">Type of Value field</typeparam>
/// <typeparam name="TError">Type of Error field</typeparam>
public struct Result<TResult, TError>
public struct Result<TResult, TError> : IEquatable<Result<TResult, TError>>
{
private readonly bool _isSuccess;

Expand Down Expand Up @@ -104,6 +134,35 @@ public static implicit operator Result<TResult, TError>(ErrorTag<TError> tag)
{
return new Result<TResult, TError>(tag.Error);
}

public static bool operator ==(Result<TResult, TError> r1, Result<TResult, TError> r2)
{
return Helpers.Equals((r1._isSuccess, r1.Value, r1.Error), (r2._isSuccess, r2.Value, r2.Error));
}

public static bool operator !=(Result<TResult, TError> r1, Result<TResult, TError> r2)
{
return !(r1 == r2);
}

public override int GetHashCode()
{
return this.IsSuccess ? this.Value.GetHashCode() : this.IsSuccess.GetHashCode();
}

public override bool Equals(object obj)
{
if (obj is Result<TResult, TError> t)
{
return this == t;
}
return false;
}

public bool Equals(Result<TResult, TError> other)
{
return this == other;
}
}

/// <summary>
Expand All @@ -112,7 +171,7 @@ public static implicit operator Result<TResult, TError>(ErrorTag<TError> tag)
/// <typeparam name="TResult">Type of Value field</typeparam>
/// <typeparam name="TError1">Type of first Error</typeparam>
/// <typeparam name="TError2">Type of second Error</typeparam>
public struct Result<TResult, TError1, TError2>
public struct Result<TResult, TError1, TError2>: IEquatable<Result<TResult, TError1, TError2>>
{
private readonly bool _isSuccess;

Expand Down Expand Up @@ -169,6 +228,35 @@ public static implicit operator Result<TResult, TError1, TError2>(ErrorTag<TErro
{
return new Result<TResult, TError1, TError2>(tag.Error);
}

public static bool operator ==(Result<TResult, TError1, TError2> r1, Result<TResult, TError1, TError2> r2)
{
return Helpers.Equals((r1._isSuccess, r1.Value, r2.Error), (r2._isSuccess, r2.Value, r2.Error));
}

public static bool operator !=(Result<TResult, TError1, TError2> r1, Result<TResult, TError1, TError2> r2)
{
return !(r1 == r2);
}

public override int GetHashCode()
{
return this.IsSuccess ? this.Value.GetHashCode() : this.IsSuccess.GetHashCode();
}

public override bool Equals(object obj)
{
if (obj is Result<TResult, TError1, TError2> t)
{
return this == t;
}
return false;
}

public bool Equals(Result<TResult, TError1, TError2> other)
{
return this == other;
}
}

/// <summary>
Expand All @@ -178,7 +266,7 @@ public static implicit operator Result<TResult, TError1, TError2>(ErrorTag<TErro
/// <typeparam name="TError1">Type of first Error</typeparam>
/// <typeparam name="TError2">Type of second Error</typeparam>
/// <typeparam name="TError3">Type of third Error</typeparam>
public struct Result<TResult, TError1, TError2, TError3>
public struct Result<TResult, TError1, TError2, TError3> : IEquatable<Result<TResult, TError1, TError2, TError3>>
{
private readonly bool _isSuccess;

Expand Down Expand Up @@ -240,5 +328,34 @@ public static implicit operator Result<TResult, TError1, TError2, TError3>(Error
{
return new Result<TResult, TError1, TError2, TError3>(tag.Error);
}

public static bool operator ==(Result<TResult, TError1, TError2, TError3> r1, Result<TResult, TError1, TError2, TError3> r2)
{
return Helpers.Equals((r1._isSuccess, r1.Value, r2.Error), (r2._isSuccess, r2.Value, r2.Error));
}

public static bool operator !=(Result<TResult, TError1, TError2, TError3> r1, Result<TResult, TError1, TError2, TError3> r2)
{
return !(r1 == r2);
}

public override int GetHashCode()
{
return this.IsSuccess ? this.Value.GetHashCode() : this.IsSuccess.GetHashCode();
}

public override bool Equals(object obj)
{
if (obj is Result<TResult, TError1, TError2> t)
{
return this == t;
}
return false;
}

public bool Equals(Result<TResult, TError1, TError2, TError3> other)
{
return this == other;
}
}
}
Loading