├── LICENSE
├── img
└── logo.png
├── .gitignore
├── tests
└── Ultimately.Tests
│ ├── Properties
│ └── AssemblyInfo.cs
│ ├── Ultimately.Tests.csproj
│ ├── EitherTests.cs
│ └── CollectionTests.cs
├── src
├── Ultimately.csproj
├── Reasons
│ ├── ExceptionalError.cs
│ ├── Reason.cs
│ ├── ReasonStringBuilder.cs
│ ├── Success.cs
│ └── Error.cs
├── Option_Unit_Lazy.cs
├── Utilities
│ ├── MissingReasons.cs
│ └── TryParse.cs
├── Option_Unit.cs
├── OptionExtensions.cs
├── Optional.cs
├── Collections
│ └── OptionCollectionExtensions.cs
└── Option_Either.cs
├── Ultimately.sln
└── README.md
/LICENSE:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/silkfire/Ultimately/HEAD/LICENSE
--------------------------------------------------------------------------------
/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/silkfire/Ultimately/HEAD/img/logo.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.suo
2 | *.user
3 | _ReSharper.*
4 | .vs
5 | bin
6 | obj
7 | packages
8 |
--------------------------------------------------------------------------------
/tests/Ultimately.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | [assembly: AssemblyTitle("Optional.Tests")]
5 | [assembly: AssemblyDescription("")]
6 | [assembly: AssemblyConfiguration("")]
7 | [assembly: AssemblyCompany("")]
8 | [assembly: AssemblyProduct("Ultimately.Tests")]
9 | [assembly: AssemblyCopyright("Copyright © 2019")]
10 | [assembly: AssemblyTrademark("")]
11 | [assembly: AssemblyCulture("")]
12 |
13 | [assembly: AssemblyVersion("1.0.0.0")]
14 | [assembly: AssemblyFileVersion("1.0.0.0")]
15 |
16 | [assembly: ComVisible(false)]
17 |
--------------------------------------------------------------------------------
/src/Ultimately.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net10.0
5 | Gabriel Bider, Nils Lück, Michael Altmann
6 | option optional some none maybe either null monad monadic result results resultful fluentresults functional pipeline pipelines
7 | https://github.com/silkfire/Ultimately
8 | A robust option type for C#.
9 | 4.0.0
10 | 4.0.0.0
11 | 4.0.0 Target .NET 10
12 |
13 |
14 |
--------------------------------------------------------------------------------
/tests/Ultimately.Tests/Ultimately.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net10.0
5 | true
6 |
7 | false
8 | Gabriel Bider, Nils Lück
9 | 1591
10 |
11 |
12 |
13 |
14 |
15 | all
16 | runtime; build; native; contentfiles; analyzers; buildtransitive
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/Reasons/ExceptionalError.cs:
--------------------------------------------------------------------------------
1 | namespace Ultimately.Reasons;
2 |
3 | using System;
4 |
5 | ///
6 | /// Represents an error that is associated with a specific exception instance.
7 | ///
8 | public sealed class ExceptionalError : Error
9 | {
10 | ///
11 | /// Gets the exception associated with this error.
12 | ///
13 | public Exception Exception { get; }
14 |
15 | private ExceptionalError(string message, Exception exception) : base(message)
16 | {
17 | Exception = exception;
18 | }
19 |
20 | ///
21 | /// Creates a new instance that wraps the specified exception.
22 | ///
23 | /// The exception to wrap.
24 | public static ExceptionalError Create(Exception exception)
25 | {
26 | return new ExceptionalError(exception.Message, exception);
27 | }
28 |
29 | ///
30 | protected internal override ReasonStringBuilder GetReasonStringBuilder()
31 | {
32 | return new ReasonStringBuilder().WithInfoNoQuotes("", $"{Exception.GetType().Name}: '{Message}'");
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Reasons/Reason.cs:
--------------------------------------------------------------------------------
1 | namespace Ultimately.Reasons;
2 |
3 | using System.Collections.Generic;
4 |
5 | // https://github.com/altmann/FluentResults
6 | ///
7 | /// Base class for representing reasons for success or failure.
8 | ///
9 | public abstract class Reason
10 | {
11 | ///
12 | /// Gets the message associated with the current object.
13 | ///
14 | public string Message { get; protected set; }
15 |
16 | ///
17 | /// Gets the collection of key-value pairs that store additional metadata associated with the object.
18 | ///
19 | public Dictionary Metadata { get; protected set; } = [];
20 |
21 | ///
22 | /// Gets a for this reason.
23 | ///
24 | protected internal virtual ReasonStringBuilder GetReasonStringBuilder()
25 | {
26 | return new ReasonStringBuilder().WithReasonType(GetType())
27 | .WithInfo("", Message)
28 | .WithInfo(nameof(Metadata), string.Join("; ", Metadata));
29 | }
30 |
31 | ///
32 | /// Returns a string representation of the reason.
33 | ///
34 | public override string ToString()
35 | {
36 | return GetReasonStringBuilder().Build();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Ultimately.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.28803.352
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ultimately", "src\Ultimately.csproj", "{BDAE4370-B7A7-41B4-BCF9-8D201C811914}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ultimately.Tests", "tests\Ultimately.Tests\Ultimately.Tests.csproj", "{12606143-9C9B-4A92-81D5-CEA814AC64AC}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {BDAE4370-B7A7-41B4-BCF9-8D201C811914}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {BDAE4370-B7A7-41B4-BCF9-8D201C811914}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {BDAE4370-B7A7-41B4-BCF9-8D201C811914}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {BDAE4370-B7A7-41B4-BCF9-8D201C811914}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {12606143-9C9B-4A92-81D5-CEA814AC64AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {12606143-9C9B-4A92-81D5-CEA814AC64AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {12606143-9C9B-4A92-81D5-CEA814AC64AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {12606143-9C9B-4A92-81D5-CEA814AC64AC}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {E57277B7-1604-4E19-94FB-95F188F94526}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/src/Option_Unit_Lazy.cs:
--------------------------------------------------------------------------------
1 | namespace Ultimately;
2 |
3 | using Reasons;
4 |
5 | using System;
6 | using System.Threading.Tasks;
7 |
8 | ///
9 | /// Wraps a predicate that returns a successful or an unsuccessful outcome.
10 | ///
11 | public readonly struct LazyOption
12 | {
13 | internal Func OutcomeDelegate { get; }
14 |
15 | internal Success Success { get; }
16 |
17 | internal Error Error { get; }
18 |
19 | internal LazyOption(Func outcomeDelegate, Success success, Error error)
20 | {
21 | OutcomeDelegate = outcomeDelegate;
22 | Success = success;
23 | Error = error;
24 | }
25 |
26 | ///
27 | /// Resolves the outcome delegate of the optional, returning a regular optional whose outcome depends on the result of the delegate.
28 | ///
29 | ///
30 | public Option Resolve()
31 | {
32 | return OutcomeDelegate() ? Optional.Some(Success) : Optional.None(Error);
33 | }
34 | }
35 |
36 | ///
37 | /// Wraps a predicate task that returns a successful or an unsuccessful outcome.
38 | ///
39 | public readonly struct LazyOptionAsync
40 | {
41 | internal Func> OutcomeDelegate { get; }
42 |
43 | internal Success Success { get; }
44 |
45 | internal Error Error { get; }
46 |
47 | internal LazyOptionAsync(Func> outcomeDelegate, Success success, Error error)
48 | {
49 | OutcomeDelegate = outcomeDelegate;
50 | Success = success;
51 | Error = error;
52 | }
53 |
54 | ///
55 | /// Resolves the outcome delegate of the optional, returning a regular optional whose outcome depends on the result of the delegate.
56 | ///
57 | ///
58 | public async Task