From 67a7f589c3f7f28ada0fdbf0cc2efe9012d83d00 Mon Sep 17 00:00:00 2001
From: Jean-Sebastien Carle <29762210+jscarle@users.noreply.github.com>
Date: Mon, 19 Feb 2024 23:50:04 -0500
Subject: [PATCH] Improved ToString() performance. (#8)
---
src/LightResults/Common/ResultBase.cs | 57 +++++--
src/LightResults/Error.cs | 15 +-
src/LightResults/Result.cs | 139 ++++++++++------
.../Benchmarks.cs | 151 +++++++++++++++---
.../Benchmarks.cs | 128 +++++++++++++--
5 files changed, 380 insertions(+), 110 deletions(-)
diff --git a/src/LightResults/Common/ResultBase.cs b/src/LightResults/Common/ResultBase.cs
index 8e45547..120bee4 100644
--- a/src/LightResults/Common/ResultBase.cs
+++ b/src/LightResults/Common/ResultBase.cs
@@ -1,6 +1,4 @@
-using System.Text;
-
-namespace LightResults.Common;
+namespace LightResults.Common;
/// Base class for implementing the interface.
public abstract class ResultBase : IResult
@@ -54,21 +52,46 @@ public bool HasError() where TError : IError
///
public override string ToString()
{
- var builder = new StringBuilder();
- builder.Append(GetType().Name);
- builder.Append(" { ");
- builder.Append("IsSuccess = ");
- builder.Append(IsSuccess);
+ var typeName = GetType().Name;
+ if (IsSuccess)
+ return GetResultString(typeName, "True", "");
- if (IsFailed && Errors[0].Message.Length > 0)
- {
- builder.Append(", Error = ");
- builder.Append('"');
- builder.Append(Errors[0].Message);
- builder.Append('"');
- }
+ var errorString = GetErrorString();
+ return GetResultString(typeName, "False", errorString);
+ }
+
+ internal static string GetResultString(string typeName, string successString, string informationString)
+ {
+ const string preResultStr = " { IsSuccess = ";
+ const string postResultStr = " }";
+#if NET6_0_OR_GREATER
+ var stringLength = typeName.Length + preResultStr.Length + successString.Length + informationString.Length + postResultStr.Length;
+
+ var str = string.Create(stringLength, (typeName, successString, informationString), (span, state) => { span.TryWrite($"{state.typeName}{preResultStr}{state.successString}{state.informationString}{postResultStr}", out _); });
+
+ return str;
+#else
+ return $"{typeName}{preResultStr}{successString}{informationString}{postResultStr}";
+#endif
+ }
+
+ internal string GetErrorString()
+ {
+ if (IsSuccess || Errors[0].Message.Length <= 0)
+ return "";
+
+ var errorMessage = Errors[0].Message;
+
+ const string preErrorStr = ", Error = \"";
+ const string postErrorStr = "\"";
+#if NET6_0_OR_GREATER
+ var stringLength = preErrorStr.Length + errorMessage.Length + postErrorStr.Length;
+
+ var str = string.Create(stringLength, errorMessage, (span, state) => { span.TryWrite($"{preErrorStr}{state}{postErrorStr}", out _); });
- builder.Append(" }");
- return builder.ToString();
+ return str;
+#else
+ return $"{preErrorStr}{errorMessage}{postErrorStr}";
+#endif
}
}
diff --git a/src/LightResults/Error.cs b/src/LightResults/Error.cs
index 73e461e..bf879d1 100644
--- a/src/LightResults/Error.cs
+++ b/src/LightResults/Error.cs
@@ -11,7 +11,7 @@ namespace LightResults;
public class Error : IError
{
internal static Error Empty { get; } = new();
-
+
///
public string Message { get; }
@@ -41,15 +41,10 @@ public Error(string message)
#endif
}
- /// Initializes a new instance of the class with the specified metadata.
- /// The metadata associated with the error.
- public Error((string Key, object Value) metadata) : this("", metadata)
- {
- }
/// Initializes a new instance of the class with the specified metadata.
/// The metadata associated with the error.
- public Error(IDictionary metadata) : this("", metadata)
+ public Error((string Key, object Value) metadata) : this("", metadata)
{
}
@@ -69,6 +64,12 @@ public Error(string message, (string Key, object Value) metadata)
#endif
}
+ /// Initializes a new instance of the class with the specified metadata.
+ /// The metadata associated with the error.
+ public Error(IDictionary metadata) : this("", metadata)
+ {
+ }
+
/// Initializes a new instance of the class with the specified error message and metadata.
/// The error message.
/// The metadata associated with the error.
diff --git a/src/LightResults/Result.cs b/src/LightResults/Result.cs
index c530179..4b6c939 100644
--- a/src/LightResults/Result.cs
+++ b/src/LightResults/Result.cs
@@ -1,4 +1,3 @@
-using System.Text;
using LightResults.Common;
namespace LightResults;
@@ -10,8 +9,8 @@ public sealed class Result : ResultBase
#endif
{
private static readonly Result OkResult = new();
- private static readonly Result FailResult = new(Error.Empty);
-
+ private static readonly Result FailedResult = new(Error.Empty);
+
private Result()
{
}
@@ -44,7 +43,7 @@ public static Result Ok(TValue value)
/// A new instance of representing a failed result.
public static Result Fail()
{
- return FailResult;
+ return FailedResult;
}
/// Creates a failed result with the given error message.
@@ -52,7 +51,8 @@ public static Result Fail()
/// A new instance of representing a failed result with the specified error message.
public static Result Fail(string errorMessage)
{
- return new Result(new Error(errorMessage));
+ var error = new Error(errorMessage);
+ return Fail(error);
}
/// Creates a failed result with the given error message and metadata.
@@ -61,7 +61,8 @@ public static Result Fail(string errorMessage)
/// A new instance of representing a failed result with the specified error message and metadata.
public static Result Fail(string errorMessage, (string Key, object Value) metadata)
{
- return new Result(new Error(errorMessage, metadata));
+ var error = new Error(errorMessage, metadata);
+ return Fail(error);
}
/// Creates a failed result with the given error message and metadata.
@@ -70,7 +71,8 @@ public static Result Fail(string errorMessage, (string Key, object Value) metada
/// A new instance of representing a failed result with the specified error message and metadata.
public static Result Fail(string errorMessage, IDictionary metadata)
{
- return new Result(new Error(errorMessage, metadata));
+ var error = new Error(errorMessage, metadata);
+ return Fail(error);
}
/// Creates a failed result with the given error.
@@ -143,6 +145,19 @@ public static Result Fail(IEnumerable errors)
{
return Result.Fail(errors);
}
+
+ ///
+ public override string ToString()
+ {
+ if (IsSuccess)
+ return $"{nameof(Result)} {{ IsSuccess = True }}";
+
+ if (Errors[0].Message.Length == 0)
+ return $"{nameof(Result)} {{ IsSuccess = False }}";
+
+ var errorString = GetErrorString();
+ return GetResultString(nameof(Result), "False", errorString);
+ }
}
/// Represents a result.
@@ -154,7 +169,7 @@ public sealed class Result : ResultBase
, IResult
#endif
{
- private static readonly Result FailResult = new(Error.Empty);
+ private static readonly Result FailedResult = new(Error.Empty);
/// Gets the value of the result, throwing an exception if the result is failed.
/// Thrown when attempting to get or set the value of a failed result.
@@ -210,7 +225,7 @@ public static Result Ok(TValue value)
/// A new instance of representing a failed result.
public static Result Fail()
{
- return FailResult;
+ return FailedResult;
}
/// Creates a failed result with the given error message.
@@ -218,7 +233,8 @@ public static Result Fail()
/// A new instance of representing a failed result with the specified error message.
public static Result Fail(string errorMessage)
{
- return new Result(new Error(errorMessage));
+ var error = new Error(errorMessage);
+ return Fail(error);
}
/// Creates a failed result with the given error message and metadata.
@@ -227,7 +243,8 @@ public static Result Fail(string errorMessage)
/// A new instance of representing a failed result with the specified error message.
public static Result Fail(string errorMessage, (string Key, object Value) metadata)
{
- return new Result(new Error(errorMessage, metadata));
+ var error = new Error(errorMessage, metadata);
+ return Fail(error);
}
/// Creates a failed result with the given error message and metadata.
@@ -236,7 +253,8 @@ public static Result Fail(string errorMessage, (string Key, object Value
/// A new instance of representing a failed result with the specified error message.
public static Result Fail(string errorMessage, IDictionary metadata)
{
- return new Result(new Error(errorMessage, metadata));
+ var error = new Error(errorMessage, metadata);
+ return Fail(error);
}
/// Creates a failed result with the given error.
@@ -258,50 +276,73 @@ public static Result Fail(IEnumerable errors)
///
public override string ToString()
{
- var builder = new StringBuilder();
- builder.Append(nameof(Result));
- builder.Append(" { ");
- builder.Append("IsSuccess = ");
- builder.Append(IsSuccess);
-
if (IsSuccess)
{
- if (Value is bool || Value is sbyte || Value is byte || Value is short || Value is ushort || Value is int || Value is uint || Value is long || Value is ulong ||
+ var valueString = GetValueString();
+ return GetResultString(nameof(Result), "True", valueString);
+ }
+
+ if (Errors[0].Message.Length == 0)
+ return $"{nameof(Result)} {{ IsSuccess = False }}";
+
+ var errorString = GetErrorString();
+ return GetResultString(nameof(Result), "False", errorString);
+ }
+
+ private string GetValueString()
+ {
+ if (IsFailed)
+ return "";
+
+ var valueString = Value?.ToString() ?? "";
+
+ const string preValueStr = ", Value = ";
+ const string charStr = "'";
+ const string stringStr = "\"";
+
+ if (Value is bool || Value is sbyte || Value is byte || Value is short || Value is ushort || Value is int || Value is uint || Value is long || Value is ulong ||
#if NET7_0_OR_GREATER
- Value is Int128 || Value is UInt128 ||
+ Value is Int128 || Value is UInt128 ||
+#endif
+ Value is decimal || Value is float || Value is double)
+ {
+#if NET6_0_OR_GREATER
+ var stringLength = preValueStr.Length + valueString.Length;
+
+ var str = string.Create(stringLength, valueString, (span, state) => { span.TryWrite($"{preValueStr}{state}", out _); });
+
+ return str;
+#else
+ return $"{preValueStr}{valueString}";
#endif
- Value is decimal || Value is float || Value is double)
- {
- builder.Append(", Value = ");
- builder.Append(Value);
- }
-
- if (Value is char)
- {
- builder.Append(", Value = ");
- builder.Append('\'');
- builder.Append(Value);
- builder.Append('\'');
- }
-
- if (Value is string)
- {
- builder.Append(", Value = ");
- builder.Append('"');
- builder.Append(Value);
- builder.Append('"');
- }
}
- if (IsFailed && Errors[0].Message.Length > 0)
+ if (Value is char)
{
- builder.Append(", Error = ");
- builder.Append('"');
- builder.Append(Errors[0].Message);
- builder.Append('"');
+#if NET6_0_OR_GREATER
+ var stringLength = preValueStr.Length + charStr.Length + valueString.Length + charStr.Length;
+
+ var str = string.Create(stringLength, valueString, (span, state) => { span.TryWrite($"{preValueStr}{charStr}{state}{charStr}", out _); });
+
+ return str;
+#else
+ return $"{preValueStr}{charStr}{valueString}{charStr}";
+#endif
}
- builder.Append(" }");
- return builder.ToString();
+ if (Value is string)
+ {
+#if NET6_0_OR_GREATER
+ var stringLength = preValueStr.Length + stringStr.Length + valueString.Length + stringStr.Length;
+
+ var str = string.Create(stringLength, valueString, (span, state) => { span.TryWrite($"{preValueStr}{stringStr}{state}{stringStr}", out _); });
+
+ return str;
+#else
+ return $"{preValueStr}{stringStr}{valueString}{stringStr}";
+#endif
+ }
+
+ return "";
}
-}
+}
\ No newline at end of file
diff --git a/tools/LightResults.CurrentBenchmarks/Benchmarks.cs b/tools/LightResults.CurrentBenchmarks/Benchmarks.cs
index ad5ec21..864ef40 100644
--- a/tools/LightResults.CurrentBenchmarks/Benchmarks.cs
+++ b/tools/LightResults.CurrentBenchmarks/Benchmarks.cs
@@ -1,76 +1,153 @@
using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Columns;
+using BenchmarkDotNet.Jobs;
+using LightResults.Common;
namespace LightResults.CurrentBenchmarks;
[MemoryDiagnoser]
+[SimpleJob(RuntimeMoniker.Net80)]
+[HideColumns(Column.Job, Column.Iterations, Column.Error, Column.StdDev, Column.Gen0, Column.Gen1, Column.Gen2)]
public class Benchmarks
{
- private const int ResultValue = 0;
- private const string ErrorMessage = "An unknown error occured.";
- private static readonly Error Error = new(ErrorMessage);
- private static readonly Result FailedResult = Result.Fail(Error);
-
[Params(100_000)]
public int Iterations { get; set; }
+ private const int ResultValue = 0;
+ private const string ErrorMessage = "An unknown error occured.";
+ private static readonly Error ErrorWithMessage = new(ErrorMessage);
+ private static readonly Result ResultOk = Result.Ok();
+ private static readonly Result ResultFail = Result.Fail();
+ private static readonly Result ResultFailWithMessage = Result.Fail(ErrorWithMessage);
+ private static readonly Result ResultTValueOk = Result.Ok(ResultValue);
+ private static readonly Result ResultTValueFail = Result.Fail();
+ private static readonly Result ResultTValueFailWithMessage = Result.Fail(ErrorWithMessage);
+ private static readonly CustomResult CustomResultOk = CustomResult.Ok();
+ private static readonly CustomResult CustomResultFail = CustomResult.Fail();
+ private static readonly CustomResult CustomResultFailWithMessage = CustomResult.Fail(ErrorWithMessage);
+
+ [Benchmark]
+ public void Develop_ResultBaseIndexer()
+ {
+ for (var iteration = 0; iteration < Iterations; iteration++)
+ _ = ResultFailWithMessage.Errors[0];
+ }
+
+ [Benchmark]
+ public void Develop_ResultBaseHasError()
+ {
+ for (var iteration = 0; iteration < Iterations; iteration++)
+ _ = ResultFailWithMessage.HasError();
+ }
+
+ [Benchmark]
+ public void Develop_ResultOkToString()
+ {
+ for (var iteration = 0; iteration < Iterations; iteration++)
+ _ = ResultOk.ToString();
+ }
+
+ [Benchmark]
+ public void Develop_ResultFailToString()
+ {
+ for (var iteration = 0; iteration < Iterations; iteration++)
+ _ = ResultFail.ToString();
+ }
+
+ [Benchmark]
+ public void Develop_ResultFailWithMessageToString()
+ {
+ for (var iteration = 0; iteration < Iterations; iteration++)
+ _ = ResultFailWithMessage.ToString();
+ }
+
+ [Benchmark]
+ public void Develop_ResultTValueOkToString()
+ {
+ for (var iteration = 0; iteration < Iterations; iteration++)
+ _ = ResultTValueOk.ToString();
+ }
+
[Benchmark]
- public void Current_ResultBaseIndexer()
+ public void Develop_ResultTValueFailToString()
{
for (var iteration = 0; iteration < Iterations; iteration++)
- _ = FailedResult.Errors[0];
+ _ = ResultTValueFail.ToString();
}
+
[Benchmark]
- public void Current_ResultBaseHasError()
+ public void Develop_ResultTValueFailWithMessageToString()
{
for (var iteration = 0; iteration < Iterations; iteration++)
- _ = FailedResult.HasError();
+ _ = ResultTValueFailWithMessage.ToString();
}
[Benchmark]
- public void Current_ResultOk()
+ public void Develop_CustomResultOkToString()
+ {
+ for (var iteration = 0; iteration < Iterations; iteration++)
+ _ = CustomResultOk.ToString();
+ }
+
+ [Benchmark]
+ public void Develop_CustomResultFailToString()
+ {
+ for (var iteration = 0; iteration < Iterations; iteration++)
+ _ = CustomResultFail.ToString();
+ }
+
+ [Benchmark]
+ public void Develop_CustomResultFailWithMessageToString()
+ {
+ for (var iteration = 0; iteration < Iterations; iteration++)
+ _ = CustomResultFailWithMessage.ToString();
+ }
+
+ [Benchmark]
+ public void Develop_ResultOk()
{
for (var iteration = 0; iteration < Iterations; iteration++)
_ = Result.Ok();
}
[Benchmark]
- public void Current_ResultFail()
+ public void Develop_ResultFail()
{
for (var iteration = 0; iteration < Iterations; iteration++)
_ = Result.Fail();
}
[Benchmark]
- public void Current_ResultFailWithError()
+ public void Develop_ResultFailWithError()
{
for (var iteration = 0; iteration < Iterations; iteration++)
- _ = Result.Fail(Error);
+ _ = Result.Fail(ErrorWithMessage);
}
[Benchmark]
- public void Current_ResultTValueOk()
+ public void Develop_ResultTValueOk()
{
for (var iteration = 0; iteration < Iterations; iteration++)
_ = Result.Ok(ResultValue);
}
[Benchmark]
- public void Current_ResultTValueFail()
+ public void Develop_ResultTValueFail()
{
for (var iteration = 0; iteration < Iterations; iteration++)
_ = Result.Fail();
}
[Benchmark]
- public void Current_ResultTValueFailWithError()
+ public void Develop_ResultTValueFailWithError()
{
for (var iteration = 0; iteration < Iterations; iteration++)
- _ = Result.Fail(Error);
+ _ = Result.Fail(ErrorWithMessage);
}
[Benchmark]
- public void Current_ResultOkTValue()
+ public void Develop_ResultOkTValue()
{
// ReSharper disable once RedundantTypeArgumentsOfMethod
for (var iteration = 0; iteration < Iterations; iteration++)
@@ -78,30 +155,56 @@ public void Current_ResultOkTValue()
}
[Benchmark]
- public void Current_ResultFailTValue()
+ public void Develop_ResultFailTValue()
{
for (var iteration = 0; iteration < Iterations; iteration++)
_ = Result.Fail();
}
[Benchmark]
- public void Current_ResultFailWithErrorTValue()
+ public void Develop_ResultFailWithErrorTValue()
{
for (var iteration = 0; iteration < Iterations; iteration++)
- _ = Result.Fail(Error);
+ _ = Result.Fail(ErrorWithMessage);
}
[Benchmark]
- public void Current_NewError()
+ public void Develop_NewError()
{
for (var iteration = 0; iteration < Iterations; iteration++)
_ = new Error();
}
[Benchmark]
- public void Current_NewErrorWithString()
+ public void Develop_NewErrorWithString()
{
for (var iteration = 0; iteration < Iterations; iteration++)
_ = new Error(ErrorMessage);
}
-}
+
+ private sealed class CustomResult : ResultBase
+ {
+ private CustomResult()
+ {
+ }
+
+ private CustomResult(IError error) : base(error)
+ {
+ }
+
+ public static CustomResult Ok()
+ {
+ return new CustomResult();
+ }
+
+ public static CustomResult Fail()
+ {
+ return new CustomResult(new Error());
+ }
+
+ public static CustomResult Fail(IError error)
+ {
+ return new CustomResult(error);
+ }
+ }
+}
\ No newline at end of file
diff --git a/tools/LightResults.DevelopBenchmarks/Benchmarks.cs b/tools/LightResults.DevelopBenchmarks/Benchmarks.cs
index f90266e..b2495b1 100644
--- a/tools/LightResults.DevelopBenchmarks/Benchmarks.cs
+++ b/tools/LightResults.DevelopBenchmarks/Benchmarks.cs
@@ -1,31 +1,107 @@
-using System.Collections.Immutable;
-using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Columns;
+using BenchmarkDotNet.Jobs;
+using LightResults.Common;
namespace LightResults.DevelopBenchmarks;
[MemoryDiagnoser]
+[SimpleJob(RuntimeMoniker.Net80)]
+[HideColumns(Column.Job, Column.Iterations, Column.Error, Column.StdDev, Column.Gen0, Column.Gen1, Column.Gen2)]
public class Benchmarks
{
- private const int ResultValue = 0;
- private const string ErrorMessage = "An unknown error occured.";
- private static readonly Error Error = new(ErrorMessage);
- private static readonly Result FailedResult = Result.Fail(Error);
-
[Params(100_000)]
public int Iterations { get; set; }
+ private const int ResultValue = 0;
+ private const string ErrorMessage = "An unknown error occured.";
+ private static readonly Error ErrorWithMessage = new(ErrorMessage);
+ private static readonly Result ResultOk = Result.Ok();
+ private static readonly Result ResultFail = Result.Fail();
+ private static readonly Result ResultFailWithMessage = Result.Fail(ErrorWithMessage);
+ private static readonly Result ResultTValueOk = Result.Ok(ResultValue);
+ private static readonly Result ResultTValueFail = Result.Fail();
+ private static readonly Result ResultTValueFailWithMessage = Result.Fail(ErrorWithMessage);
+ private static readonly CustomResult CustomResultOk = CustomResult.Ok();
+ private static readonly CustomResult CustomResultFail = CustomResult.Fail();
+ private static readonly CustomResult CustomResultFailWithMessage = CustomResult.Fail(ErrorWithMessage);
+
[Benchmark]
public void Develop_ResultBaseIndexer()
{
for (var iteration = 0; iteration < Iterations; iteration++)
- _ = FailedResult.Errors[0];
+ _ = ResultFailWithMessage.Errors[0];
}
[Benchmark]
public void Develop_ResultBaseHasError()
{
for (var iteration = 0; iteration < Iterations; iteration++)
- _ = FailedResult.HasError();
+ _ = ResultFailWithMessage.HasError();
+ }
+
+ [Benchmark]
+ public void Develop_ResultOkToString()
+ {
+ for (var iteration = 0; iteration < Iterations; iteration++)
+ _ = ResultOk.ToString();
+ }
+
+ [Benchmark]
+ public void Develop_ResultFailToString()
+ {
+ for (var iteration = 0; iteration < Iterations; iteration++)
+ _ = ResultFail.ToString();
+ }
+
+ [Benchmark]
+ public void Develop_ResultFailWithMessageToString()
+ {
+ for (var iteration = 0; iteration < Iterations; iteration++)
+ _ = ResultFailWithMessage.ToString();
+ }
+
+ [Benchmark]
+ public void Develop_ResultTValueOkToString()
+ {
+ for (var iteration = 0; iteration < Iterations; iteration++)
+ _ = ResultTValueOk.ToString();
+ }
+
+ [Benchmark]
+ public void Develop_ResultTValueFailToString()
+ {
+ for (var iteration = 0; iteration < Iterations; iteration++)
+ _ = ResultTValueFail.ToString();
+ }
+
+
+ [Benchmark]
+ public void Develop_ResultTValueFailWithMessageToString()
+ {
+ for (var iteration = 0; iteration < Iterations; iteration++)
+ _ = ResultTValueFailWithMessage.ToString();
+ }
+
+ [Benchmark]
+ public void Develop_CustomResultOkToString()
+ {
+ for (var iteration = 0; iteration < Iterations; iteration++)
+ _ = CustomResultOk.ToString();
+ }
+
+ [Benchmark]
+ public void Develop_CustomResultFailToString()
+ {
+ for (var iteration = 0; iteration < Iterations; iteration++)
+ _ = CustomResultFail.ToString();
+ }
+
+ [Benchmark]
+ public void Develop_CustomResultFailWithMessageToString()
+ {
+ for (var iteration = 0; iteration < Iterations; iteration++)
+ _ = CustomResultFailWithMessage.ToString();
}
[Benchmark]
@@ -46,7 +122,7 @@ public void Develop_ResultFail()
public void Develop_ResultFailWithError()
{
for (var iteration = 0; iteration < Iterations; iteration++)
- _ = Result.Fail(Error);
+ _ = Result.Fail(ErrorWithMessage);
}
[Benchmark]
@@ -67,7 +143,7 @@ public void Develop_ResultTValueFail()
public void Develop_ResultTValueFailWithError()
{
for (var iteration = 0; iteration < Iterations; iteration++)
- _ = Result.Fail(Error);
+ _ = Result.Fail(ErrorWithMessage);
}
[Benchmark]
@@ -89,7 +165,7 @@ public void Develop_ResultFailTValue()
public void Develop_ResultFailWithErrorTValue()
{
for (var iteration = 0; iteration < Iterations; iteration++)
- _ = Result.Fail(Error);
+ _ = Result.Fail(ErrorWithMessage);
}
[Benchmark]
@@ -105,4 +181,30 @@ public void Develop_NewErrorWithString()
for (var iteration = 0; iteration < Iterations; iteration++)
_ = new Error(ErrorMessage);
}
-}
+
+ private sealed class CustomResult : ResultBase
+ {
+ private CustomResult()
+ {
+ }
+
+ private CustomResult(IError error) : base(error)
+ {
+ }
+
+ public static CustomResult Ok()
+ {
+ return new CustomResult();
+ }
+
+ public static CustomResult Fail()
+ {
+ return new CustomResult(new Error());
+ }
+
+ public static CustomResult Fail(IError error)
+ {
+ return new CustomResult(error);
+ }
+ }
+}
\ No newline at end of file