{"id":23240713,"url":"https://github.com/skbkontur/results","last_synced_at":"2025-04-09T15:06:33.114Z","repository":{"id":73236603,"uuid":"427068784","full_name":"skbkontur/results","owner":"skbkontur","description":null,"archived":false,"fork":false,"pushed_at":"2024-12-17T20:55:19.000Z","size":4490,"stargazers_count":22,"open_issues_count":1,"forks_count":2,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-04-09T15:06:27.679Z","etag":null,"topics":["csharp"],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/skbkontur.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-11-11T16:27:35.000Z","updated_at":"2025-03-11T15:47:07.000Z","dependencies_parsed_at":"2025-01-09T15:46:46.880Z","dependency_job_id":"5117ce03-05dc-4a59-832e-6f240e3f1a88","html_url":"https://github.com/skbkontur/results","commit_stats":{"total_commits":64,"total_committers":3,"mean_commits":"21.333333333333332","dds":0.046875,"last_synced_commit":"145846fefd7e9661b1e2b5b48e9f2a156a9cde14"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skbkontur%2Fresults","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skbkontur%2Fresults/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skbkontur%2Fresults/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skbkontur%2Fresults/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skbkontur","download_url":"https://codeload.github.com/skbkontur/results/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248055284,"owners_count":21040157,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp"],"created_at":"2024-12-19T05:13:47.225Z","updated_at":"2025-04-09T15:06:33.099Z","avatar_url":"https://github.com/skbkontur.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Yet another `Result` types implementation\n\n[![NuGet](https://img.shields.io/nuget/v/Kontur.Results.svg)](https://www.nuget.org/packages/Kontur.Results/)\n\n\nThis library consists of three `Result` types with some tempting [features](#features) :\n* `Optional\u003cTValue\u003e`\n* `Result\u003cTFault\u003e`\n* `Result\u003cTFault, TValue\u003e`\n\n## Content\n\n* [License](#license)\n* [Installation](#installation)\n    * [Nuget](#nuget)\n    * [Cement](#cement)\n* [Examples](#examples)\n* [Features](#features)\n* [Drawbacks](#drawbacks)\n* [Instantiation of types](#instantiation-of-types)\n* [Extraction of data from instances](#extraction-of-data-from-instances)\n    * [TryGetValue](#trygetvalue)\n    * [TryGetFault](#trygetfault)\n    * [Match](#match)\n    * [Switch](#switch)\n    * [OnSome](#onsome)\n    * [OnNone](#onnone)\n    * [OnSuccess](#onsuccess)\n    * [OnFailure](#onfailure)\n    * [Switch/OnSome/OnNone/OnSuccess/OnFailure method chaining](#switchonsomeonnoneonsuccessonfailure-method-chaining)\n    * [Switch/OnSome/OnNone/OnSuccess/OnFailure return value upcasting](#switchonsomeonnoneonsuccessonfailure-return-value-upcasting)\n    * [GetValueOrElse](#getvalueorelse)\n    * [GetFaultOrElse](#getfaultorelse)\n    * [GetValueOrThrow](#getvalueorthrow)\n    * [GetFaultOrThrow](#getfaultorthrow)\n    * [GetValueOrDefault](#getvalueordefault)\n    * [GetFaultOrDefault](#getfaultordefault)\n    * [GetValueOrNull](#getvalueornull)\n    * [GetFaultOrNull](#getfaultornull)\n    * [EnsureHasValue](#ensurehasvalue)\n    * [EnsureNone](#ensurenone)\n    * [EnsureSuccess](#ensuresuccess)\n    * [EnsureFailure](#ensurefailure)\n    * [HasSome](#hassome)\n    * [IsNone](#isnone)\n    * [Success](#success)\n    * [Failure](#failure)\n    * [LINQ method syntax (GetValues, GetFaults)](#linq-method-syntax-getvalues-getfaults)\n    * [LINQ query syntax](#linq-query-syntax)\n    * [foreach](#foreach)\n    * [ToString](#tostring)\n    * [Upcasts](#upcasts)\n* [Conversion of generic arguments](#conversion-of-generic-arguments)\n    * [MapValue](#mapvalue)\n    * [MapFault](#mapfault)\n    * [Upcast](#upcast)\n* [Result combining](#result-combining) or monadic extensions\n    * [Then](#then)\n    * [OrElse](#orelse)\n    * [Then/OrElse method chaining](#thenorelse-method-chaining)\n    * [Select](#select)\n    * [Do notation](#do-notation)\n    * [Do notation with async extensions](#do-notation-with-async-extensions)\n* [Inheritance](#inheritance)\n* [Other](#other)\n* [Yet to be implemented](#yet-to-be-implemented)\n* [Contributing](#contributing)\n\n\n## License\n\nMIT\n\n\n## Installation\n\n### Nuget\n\nExecute that command in Package Manager console to install [Kontur.Results](https://www.nuget.org/packages/Kontur.Results/):\n\n`Install-Package Kontur.Results -Version 1.0.1`\n\nExecute the following command instead to install [Kontur.Results.Monad](https://www.nuget.org/packages/Kontur.Results.Monad/) if you are willing for [monadic extensions](#result-combining) (implemented separately). It consists of [Then](#then), [OrElse](#orelse), [Select](#select) and [do notation](#do-notation-with-async-extensions):\n\n`Install-Package Kontur.Results.Monad -Version 1.0.1`\n\n### Cement\n\nUse [cement](https://github.com/skbkontur/cement#get-started) to add a reference to `Kontur.Results` assembly.\n\nExecute that command in your cement module:\n\n`cm ref add results your-csproj.csproj`\n\nExecute the following command in your cement module instead if you are willing for [monadic extensions](#result-combining) (implemented separately). It consists of [Then](#then), [OrElse](#orelse), [Select](#select) and [do notation](#do-notation-with-async-extensions):\n\n`cm ref add results/monad your-csproj.csproj`\n\n## Examples\n\n\u003cdetails\u003e\n  \u003csummary\u003eChecking Result status and extracting data with single method\u003c/summary\u003e\n\n```csharp\nusing Kontur.Results;\n\nResult\u003cint, string\u003e result = \"success!\"; // implicit conversion\n\nif (result.TryGetValue(out string value, out var faultCode))\n{\n   Console.WriteLine(value.ToString()) // OK. Value is not null here. The compiler allows this.\n}\n\nConsole.WriteLine(\"Error code: \" + faultCode);\nConsole.WriteLine(value.ToString()) // warning CS8602: Dereference of a possibly null reference.\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eConverting Result-way error handling to exception-way error handling\u003c/summary\u003e\n\n```csharp\nusing Kontur.Results;\n\nclass DraftError\n{\n  public int Code { get; init; }\n}\n\nclass DraftClient\n{\n   ...\n   public Task\u003cResult\u003cDraftError, Draft\u003e\u003e CreateDraft()\n   {\n     ...\n   }\n}\n\nResult\u003cDraftError, Draft\u003e createDraftResult = await new DraftClient().CreateDraft();\ntry\n{\n  Draft draft = createDraftResult.GetValueOrThrow();\n  Console.WriteLine(draft.Id);\n}\ncatch (ResultFailedException\u003cDraftError\u003e ex)\n{\n  Console.WriteLine(\"Error code: \" + ex.Fault.Code));\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eWorking with values without extracting it from Result instances\u003c/summary\u003e\n\n```csharp\nabstract Task\u003cOptional\u003cstring\u003e\u003e GetFormLogin();\nabstract Optional\u003cGuid\u003e GetUser(LoginModel login);\nabstract ValueTask\u003cOptional\u003cGuid\u003e\u003e CreateUser(LoginModel login);\n\nTask\u003cOptional\u003cGuid\u003e\u003e userId =\n   GetFormLogin()\n  .MapValue(str =\u003e new LoginModel(str))\n  .Then(login =\u003e GetUser(login).OrElse(() =\u003e CreateUser(login)))\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eDo notation reduces the count of checks and await operators significantly\u003c/summary\u003e\n\n```csharp\nabstract ValueTask\u003cResult\u003cException, Guid\u003e\u003e GetCurrentUserId();\nabstract Result\u003cException\u003e EnsureUserIdIsCorrect(Guid userId);\nabstract Task\u003cint\u003e GetCurrentIndex();\nabstract Task\u003cResult\u003cException, string\u003e\u003e GetMessage(Guid userId, int index);\nabstract Result\u003cException, ConvertResult\u003e Convert(string message, Guid userId);\n\nTask\u003cResult\u003cException, ConvertResult\u003e\u003e result =\n  from userId  in GetCurrentUserId()\n  where EnsureUserIdIsCorrect(userId)\n  from index   in GetCurrentIndex()\n  let nextIndex = index + 1\n  from message in GetMessage(userId, nextIndex)\n  select Convert(message, userId);\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eData parsing\u003c/summary\u003e\n\n```csharp\nclass NaturalNumber\n{\n  private readonly int value;\n  private NaturalNumber(int value) =\u003e this.value = value;\n  public static NaturalNumber operator +(NaturalNumber a, NaturalNumber b) =\u003e new NaturalNumber(a.value + b.value);\n\n  public static bool TryParse(int value, [MaybeNullWhen(returnValue: false)] out NaturalNumber number)\n  {\n    if (value \u003e 0)\n    {\n      number = new NaturalNumber(value);\n      return true;\n    }\n    number = null;\n    return false;\n  }\n\n  public static Optional\u003cNaturalNumber\u003e TryParse(int value) =\u003e TryParse(value, out var number) ? number : Optional.None();\n  public static NaturalNumber Parse(int value) =\u003e TryParse(value).GetValueOrThrow();\n}\n\nResult\u003cException, int\u003e TryParseString(string input) =\u003e int.TryParse(input, out var number)\n  ? number\n  : new Exception(input + \" is not an integer\");\n\nResult\u003cException, NaturalNumber\u003e result =\n  from int1 in TryParseString(Console.ReadLine())\n  from natural1 in NaturalNumber.TryParse(int1).OrElse(Result.Fail(new Exception(int1 + \" is not positive\")))\n  from int2 in TryParseString(Console.ReadLine())\n  from natural2 in NaturalNumber.TryParse(int2).OrElse(Result.Fail(new Exception(int2 + \" is not positive\")))\n  select natural1 + natural2;\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eInheritance to freeze fault type\u003c/summary\u003e\n\n```csharp\nclass StringFaultResult\u003cTValue\u003e : Result\u003cstring, TValue\u003e\n{\n  private readonly Result\u003cstring, TValue\u003e result;\n\n  public StringFaultResult(string fault) =\u003e result = fault;\n  public StringFaultResult(TValue value) =\u003e result = value;\n\n  public override TResult Match\u003cTResult\u003e(Func\u003cstring, TResult\u003e onFailure, Func\u003cTValue, TResult\u003e onSuccess)\n    =\u003e result.Match(onFailure, onSuccess);\n}\n\npublic StringFaultResult\u003cint\u003e GenerateInt()\n{\n  int randomValue = new Random().Next(0, 10);\n  if (randomValue \u003e 0)\n  {\n    return new StringFaultResult\u003cint\u003e(randomValue);\n  }\n\n  return new StringFaultResult\u003cint\u003e(\"Failed to generate a positive number\");\n}\n```\n\u003c/details\u003e\n\n## Features\n\n* [Do notation](#do-notation-with-async-extensions) with support of async (`Task` and `ValueTask`) execution and without limit on the expression count.\n* [Then](#then) (`And`, `ContinueWith`, `ContinueOnSome`, `Bind`) and [OrElse](#orelse) (`Or`, `Else`, `Catch`, `ContinueOnNone`) async extensions that allow chaining.\n\n* Great interface that allows checking and extracting of data with a single method. See [TryGetValue](#trygetvalue) and [Match](#match).\n* Explicit behavior of methods. See [GetValueOrThrow](#getvalueorthrow) and [GetValueOrDefault](#getvalueordefault). There is no `.Result` or `.Value` or `.Data` properties that have undefined or unexpected behavior if there are no succesful result.\n\n* `TValue` and `TFault` generic parameters are not restricted in any way.\n* There is no specific handling of null values. So you can store `nulls` as `TValue` or `TFault`. Use C# 8 nullable reference types to handle nulls.\n\n* Assemblies contain only three `Result` type implementations and extension methods for them. There is no other stuff.\n\n* `Result\u003cTFault, TValue\u003e` has no third state. It is restricted by a schema and the compiler that only two states are possible in memory of an application. One of them is `HasValue`. Other one is `HasFault`. So there are no `bottom` or `empty` state.\n* `Result` type implementations are if-less and make use of abstract classes polymorphism and VMT to maintain simplicity and error safety. As a result, there is no null-forgiving operator and no third state. Also, there are no ternary operators that check `Success` flag or similar stuff.\n* [Inheritance](#inheritance) allows to freeze or limit generic `TFault` and `TValue` parameters with user custom type arguments.\n\n## Drawbacks\n\n* To enable some features the implementation is based on abstract classes polymorphism. So `Result` types are not marked `readonly` (but they are implemented as readonly) and are not `struct`.\n\n\n## Instantiation of types\n\nExplicit examples:\n```csharp\nvar optional = Optional.Some(\"hello\"); // Optional\u003cstring\u003e\nvar optional = Optional\u003cstring\u003e.Some(\"hello\"); // Optional\u003cstring\u003e\n\nvar result = Result\u003cException\u003e.Succeed(\"hello\"); // Result\u003cException, string\u003e\nvar result = Result\u003cException, string\u003e.Succeed(\"hello\"); // Result\u003cException, string\u003e\n\nvar result = Result\u003cException\u003e.Succeed(); // Result\u003cException\u003e\nvar result = Result.Succeed\u003cException\u003e(); // Result\u003cException\u003e\n```\n\n```csharp\nvar optional = Optional.None\u003cstring\u003e(); // Optional\u003cstring\u003e\nvar optional = Optional\u003cstring\u003e.None(); // Optional\u003cstring\u003e\n\nvar result = ResultFailure\u003cstring\u003e.Create(new Exception()); // Result\u003cException, string\u003e\nvar result = Result\u003cException, string\u003e.Fail(new Exception()); // Result\u003cException, string\u003e\n\nvar result = Result.Fail(new Exception()); // Result\u003cException\u003e\nvar result = Result\u003cException\u003e.Fail(new Exception()); // Result\u003cException\u003e\n```\n\nImplicit examples:\n```csharp\nOptional\u003cstring\u003e optional = \"hello\";\nOptional\u003cstring\u003e optional = Optional.None();\n\nResult\u003cException, string\u003e result = \"hello\";\nResult\u003cException, string\u003e result = new Exception();\nResult\u003cint, int\u003e result = Result.Succeed(55);\nResult\u003cint, int\u003e result = Result.Fail(0);\n\nResult\u003cException\u003e result = Result.Succeed();\nResult\u003cException\u003e result = new Exception();\n```\n\n```csharp\nOptional\u003cstring\u003e optional = flag\n  ? \"Hello\"\n  : Optional.None();\n\nvar optional = flag\n  ? Optional.Some(\"Hello\")\n  : Optional.None();\n\nvar optional = flag\n  ? \"Hello\"\n  : Optional\u003cstring\u003e.None();\n\n```\n\n```csharp\nResult\u003cException, string\u003e result = flag\n  ? \"hello\"\n  : new Exception();\n\nvar result = flag\n  ? \"hello\"\n  : ResultFailure\u003cstring\u003e.Create(new Exception());\n\nvar result = flag\n  ? Result\u003cException\u003e.Succeed(\"hello\")\n  : new Exception();\n\nResult\u003cint, int\u003e result = flag\n  ? Result.Succeed(0)\n  : Result.Fail(-1);\n\nvar result = flag\n  ? Result\u003cint\u003e.Succeed(0)\n  : Result.Fail(-1);\n\nvar result = flag\n  ? Result.Succeed(0)\n  : ResultFailure\u003cint\u003e.Create(-1);\n```\n\n```csharp\nResult\u003cException\u003e = flag\n  ? new Exception()\n  : Result.Succeed();\n\nvar result = flag\n  ? Result\u003cException\u003e.Fail(new Exception())\n  : Result.Succeed();\n\nvar result = flag\n  ? new Exception()\n  : Result\u003cException\u003e.Succeed();\n\n```\n\nSome conversions:\n```csharp\nResult\u003cException, int\u003e source = ...\n\nResult\u003cException\u003e target = source;\n```\n\n```csharp\nOptional\u003cint\u003e GetResult(Random random)\n{\n  int randomValue = random.Next(0, 10);\n  if (randomValue \u003e 10)\n  {\n    return randomValue;\n  }\n\n  return Optional.None();\n}\n```\n\n\n## Extraction of data from instances\n\n### TryGetValue\n```csharp\nOptional\u003cstring\u003e optional = ...;\n\nif (optional.TryGetValue(out string value))\n{\n  // value is not null here\n}\n\n// value may be null here. If you used it, you would get \"warning CS8602: Dereference of a possibly null reference\"\n```\n\n```csharp\nResult\u003cException, string\u003e result = ...;\n\nif (result.TryGetValue(out string value))\n{\n  // value is not null here\n}\n\n// value may be null here. If you used it, you would get \"warning CS8602: Dereference of a possibly null reference\"\n```\n\n```csharp\nResult\u003cException, string\u003e result = ...;\n\nif (result.TryGetValue(out string value, out Exception fault))\n{\n  // value is not null here\n  // fault may be null here. If you used it, you would get \"warning CS8602: Dereference of a possibly null reference\"\n}\nelse\n{\n  // fault is not null here\n  // value may be null here. If you used it, you would get \"warning CS8602: Dereference of a possibly null reference\"\n}\n\n// Both value and fault may be null here. If you used any of them, you would get \"warning CS8602: Dereference of a possibly null reference\"\n\n```\n\n### TryGetFault\n```csharp\nResult\u003cException\u003e result = ...;\n\nif (result.TryGetFault(out Exception fault))\n{\n  // fault is not null here\n}\n\n// fault may be null here. If you used it, you would get \"warning CS8602: Dereference of a possibly null reference\"\n```\n\n```csharp\nResult\u003cException, string\u003e result = ...;\n\nif (result.TryGetFault(out Exception fault))\n{\n  // fault is not null here\n}\n\n// fault may be null here. If you used it, you would get \"warning CS8602: Dereference of a possibly null reference\"\n```\n\n```csharp\nResult\u003cException, string\u003e result = ...;\n\nif (result.TryGetFault(out Exception fault, out string value))\n{\n  // fault is not null here\n  // value may be null here. If you used it, you would get \"warning CS8602: Dereference of a possibly null reference\"\n}\nelse\n{\n  // value is not null here\n  // fault may be null here. If you use it, you get \"warning CS8602: Dereference of a possibly null reference\"\n}\n\n// Both value and fault may be null here. If you used any of them, you would get \"warning CS8602: Dereference of a possibly null reference\"\n```\n\n### Match\n```csharp\nOptional\u003cint\u003e optional = ...;\n\nstring extracted = optional.Match(onNone: () =\u003e \"valueOnNone\", onSome: i =\u003e $\"Number {i}\");\nstring extracted = optional.Match(onNone: () =\u003e \"valueOnNone\", onSome: () =\u003e \"Number is present\");\nstring extracted = optional.Match(onNone: () =\u003e \"valueOnNone\", onSomeValue: \"Number is present\");\nstring extracted = optional.Match(onNoneValue: \"valueOnNone\", onSome: i =\u003e $\"Number {i}\");\nstring extracted = optional.Match(onNoneValue: \"valueOnNone\", onSome: () =\u003e \"Number is present\");\nstring extracted = optional.Match(onNoneValue: \"valueOnNone\", onSomeValue: \"Number is present\");\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eExamples with upcast\u003c/summary\u003e\n\n```csharp\nobject upcasted = optional.Match(onNone: () =\u003e new object(), onSome: i =\u003e $\"Number {i}\");\nobject upcasted = optional.Match(onNone: () =\u003e new object(), onSome: () =\u003e \"Number is present\");\nobject upcasted = optional.Match(onNone: () =\u003e new object(), onSomeValue: \"Number is present\");\nobject upcasted = optional.Match(onNoneValue: new object(), onSome: i =\u003e $\"Number {i}\");\nobject upcasted = optional.Match(onNoneValue: new object(), onSome: () =\u003e \"Number is present\");\nobject upcasted = optional.Match(onNoneValue: new object(), onSomeValue: \"Number is present\");\n\nobject upcasted = optional.Match(onNone: () =\u003e \"valueOnNone\", onSome: _ =\u003e new object());\nobject upcasted = optional.Match(onNone: () =\u003e \"valueOnNone\", onSome: () =\u003e new object());\nobject upcasted = optional.Match(onNone: () =\u003e \"valueOnNone\", onSomeValue: new object());\nobject upcasted = optional.Match(onNoneValue: \"valueOnNone\", onSome: _ =\u003e new object());\nobject upcasted = optional.Match(onNoneValue: \"valueOnNone\", onSome: () =\u003e new object());\nobject upcasted = optional.Match(onNoneValue: \"valueOnNone\", onSomeValue: new object());\n\nobject upcasted = optional.Match\u003cobject\u003e(onNone: () =\u003e new Exception(\"There is no value\"), onSome: i =\u003e $\"Number {i}\");\nobject upcasted = optional.Match\u003cobject\u003e(onNone: () =\u003e new Exception(\"There is no value\"), onSome: () =\u003e \"Number is present\");\nobject upcasted = optional.Match\u003cobject\u003e(onNone: () =\u003e new Exception(\"There is no value\"), onSomeValue: \"Number is present\");\nobject upcasted = optional.Match\u003cobject\u003e(onNoneValue: new Exception(\"There is no value\"), onSome: i =\u003e $\"Number {i}\");\nobject upcasted = optional.Match\u003cobject\u003e(onNoneValue: new Exception(\"There is no value\"), onSome: () =\u003e \"Number is present\");\nobject upcasted = optional.Match\u003cobject\u003e(onNoneValue: new Exception(\"There is no value\"), onSomeValue: \"Number is present\");\n```\n\u003c/details\u003e\n\n```csharp\nResult\u003cException, int\u003e result = ...;\n\nstring extracted = result.Match(onFailure: ex =\u003e ex.Message, onSuccess: i =\u003e $\"Number {i}\");\nstring extracted = result.Match(onFailure: ex =\u003e ex.Message, onSuccess: () =\u003e \"Number is present\");\nstring extracted = result.Match(onFailure: ex =\u003e ex.Message, onSuccessValue: \"Number is present\");\nstring extracted = result.Match(onFailure: () =\u003e \"valueOnNone\", onSuccess: i =\u003e $\"Number {i}\");\nstring extracted = result.Match(onFailure: () =\u003e \"valueOnNone\", onSuccess: () =\u003e \"Number is present\");\nstring extracted = result.Match(onFailure: () =\u003e \"valueOnNone\", onSuccessValue: \"Number is present\");\nstring extracted = result.Match(onFailureValue: \"valueOnNone\", onSuccess: i =\u003e $\"Number {i}\");\nstring extracted = result.Match(onFailureValue: \"valueOnNone\", onSuccess: () =\u003e \"Number is present\");\nstring extracted = result.Match(onFailureValue: \"valueOnNone\", onSuccessValue: \"Number is present\");\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eExamples with upcast\u003c/summary\u003e\n\n```csharp\nobject upcasted = result.Match(onFailure: ex =\u003e new object(), onSuccess: i =\u003e $\"Number {i}\");\nobject upcasted = result.Match(onFailure: ex =\u003e new object(), onSuccess: () =\u003e \"Number is present\");\nobject upcasted = result.Match(onFailure: ex =\u003e new object(), onSuccessValue: \"Number is present\");\nobject upcasted = result.Match(onFailure: () =\u003e new object(), onSuccess: i =\u003e $\"Number {i}\");\nobject upcasted = result.Match(onFailure: () =\u003e new object(), onSuccess: () =\u003e \"Number is present\");\nobject upcasted = result.Match(onFailure: () =\u003e new object(), onSuccessValue: \"Number is present\");\nobject upcasted = result.Match(onFailureValue: new object(), onSuccess: i =\u003e $\"Number {i}\");\nobject upcasted = result.Match(onFailureValue: new object(), onSuccess: () =\u003e \"Number is present\");\nobject upcasted = result.Match(onFailureValue: new object(), onSuccessValue: \"Number is present\");\n\nobject upcasted = result.Match(onFailure: ex =\u003e ex.Message, onSuccess: _ =\u003e new object());\nobject upcasted = result.Match(onFailure: ex =\u003e ex.Message, onSuccess: () =\u003e new object());\nobject upcasted = result.Match(onFailure: ex =\u003e ex.Message, onSuccessValue: new object());\nobject upcasted = result.Match(onFailure: () =\u003e \"valueOnNone\", onSuccess: _ =\u003e new object());\nobject upcasted = result.Match(onFailure: () =\u003e \"valueOnNone\", onSuccess: () =\u003e new object());\nobject upcasted = result.Match(onFailure: () =\u003e \"valueOnNone\", onSuccessValue: new object());\nobject upcasted = result.Match(onFailureValue: \"valueOnNone\", onSuccess: _ =\u003e new object());\nobject upcasted = result.Match(onFailureValue: \"valueOnNone\", onSuccess: () =\u003e new object());\nobject upcasted = result.Match(onFailureValue: \"valueOnNone\", onSuccessValue: new object());\n\nobject upcasted = result.Match\u003cobject\u003e(onFailure: ex =\u003e ex.Message, onSuccess: i =\u003e $\"Number {i}\");\nobject upcasted = result.Match\u003cobject\u003e(onFailure: ex =\u003e ex.Message, onSuccess: () =\u003e \"Number is present\");\nobject upcasted = result.Match\u003cobject\u003e(onFailure: ex =\u003e ex.Message), onSuccessValue: \"Number is present\");\nobject upcasted = result.Match\u003cobject\u003e(onFailure: () =\u003e new Exception(\"There is no value\"), onSuccess: i =\u003e $\"Number {i}\");\nobject upcasted = result.Match\u003cobject\u003e(onFailure: () =\u003e new Exception(\"There is no value\"), onSuccess: () =\u003e \"Number is present\");\nobject upcasted = result.Match\u003cobject\u003e(onFailure: () =\u003e new Exception(\"There is no value\"), onSuccessValue: \"Number is present\");\nobject upcasted = result.Match\u003cobject\u003e(onFailureValue: new Exception(\"There is no value\"), onSuccess: i =\u003e $\"Number {i}\");\nobject upcasted = result.Match\u003cobject\u003e(onFailureValue: new Exception(\"There is no value\"), onSuccess: () =\u003e \"Number is present\");\nobject upcasted = result.Match\u003cobject\u003e(onFailureValue: new Exception(\"There is no value\"), onSuccessValue: \"Number is present\");\n```\n\u003c/details\u003e\n\n```csharp\nResult\u003cException\u003e result = ...;\n\nstring extracted = result.Match(onFailure: ex =\u003e ex.Message, onSuccess: () =\u003e \"Fault is not present\");\nstring extracted = result.Match(onFailure: ex =\u003e ex.Message, onSuccessValue: \"Fault is not present\");\nstring extracted = result.Match(onFailure: () =\u003e \"valueOnNone\", onSuccess: () =\u003e \"Fault is not present\");\nstring extracted = result.Match(onFailure: () =\u003e \"valueOnNone\", onSuccessValue: \"Fault is not present\");\nstring extracted = result.Match(onFailureValue: \"valueOnNone\", onSuccess: () =\u003e \"Fault is not present\");\nstring extracted = result.Match(onFailureValue: \"valueOnNone\", onSuccessValue: \"Fault is not present\");\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eExamples with upcast\u003c/summary\u003e\n\n```csharp\nobject upcasted = result.Match(onFailure: ex =\u003e new object(), onSuccess: () =\u003e \"Fault is not present\");\nobject upcasted = result.Match(onFailure: ex =\u003e new object(), onSuccessValue: \"Fault is not present\");\nobject upcasted = result.Match(onFailure: () =\u003e new object(), onSuccess: () =\u003e \"Fault is not present\");\nobject upcasted = result.Match(onFailure: () =\u003e new object(), onSuccessValue: \"Fault is not present\");\nobject upcasted = result.Match(onFailureValue: new object(), onSuccess: () =\u003e \"Fault is not present\");\nobject upcasted = result.Match(onFailureValue: new object(), onSuccessValue: \"Fault is not present\");\n\nobject upcasted = result.Match(onFailure: ex =\u003e ex.Message, onSuccess: () =\u003e new object());\nobject upcasted = result.Match(onFailure: ex =\u003e ex.Message, onSuccessValue: new object());\nobject upcasted = result.Match(onFailure: () =\u003e \"valueOnNone\", onSuccess: () =\u003e new object());\nobject upcasted = result.Match(onFailure: () =\u003e \"valueOnNone\", onSuccessValue: new object());\nobject upcasted = result.Match(onFailureValue: \"valueOnNone\", onSuccess: () =\u003e new object());\nobject upcasted = result.Match(onFailureValue: \"valueOnNone\", onSuccessValue: new object());\n\nobject upcasted = result.Match\u003cobject\u003e(onFailure: ex =\u003e ex.Message, onSuccess: () =\u003e \"Fault is not present\");\nobject upcasted = result.Match\u003cobject\u003e(onFailure: ex =\u003e ex.Message), onSuccessValue: \"Fault is not present\");\nobject upcasted = result.Match\u003cobject\u003e(onFailure: () =\u003e new Exception(), onSuccess: () =\u003e \"Fault is not present\");\nobject upcasted = result.Match\u003cobject\u003e(onFailure: () =\u003e new Exception(), onSuccessValue: \"Fault is not present\");\nobject upcasted = result.Match\u003cobject\u003e(onFailureValue: new Exception(), onSuccess: () =\u003e \"Fault is not present\");\nobject upcasted = result.Match\u003cobject\u003e(onFailureValue: new Exception(), onSuccessValue: \"Fault is not present\");\n```\n\u003c/details\u003e\n\n\n### Switch\n```csharp\nOptional\u003cint\u003e optional = ...;\n\noptional.Switch(\n  onNone: () =\u003e Console.WriteLine(\"There is no value\"),\n  onSome: value =\u003e Console.WriteLine($\"Value is {value}\")\n);\n\noptional.Switch(\n  onNone: () =\u003e Console.WriteLine(\"There is no value\"),\n  onSome: () =\u003e Console.WriteLine(\"Value is present\")\n);\n```\n\n```csharp\nResult\u003cException, int\u003e result = ...;\n\nresult.Switch(\n  onFailure: fault =\u003e Console.WriteLine(\"Fault is {fault.Message}\"),\n  onSuccess: value =\u003e Console.WriteLine($\"Value is {value}\")\n);\n\nresult.Switch(\n  onFailure: fault =\u003e Console.WriteLine(\"There is {fault.Message}\"),\n  onSuccess: () =\u003e Console.WriteLine($\"Value is present\")\n);\n\nresult.Switch(\n  onFailure: () =\u003e Console.WriteLine(\"Fault is present\"),\n  onSuccess: value =\u003e Console.WriteLine($\"Value is {value}\")\n);\n\nresult.Switch(\n  onFailure: () =\u003e Console.WriteLine(\"Fault is present\"),\n  onSuccess: () =\u003e Console.WriteLine(\"Value is present\")\n);\n```\n\n```csharp\nResult\u003cException\u003e result = ...;\n\nresult.Switch(\n  onFailure: fault =\u003e Console.WriteLine(\"Fault is {fault.Message}\"),\n  onSuccess: () =\u003e Console.WriteLine($\"There is no fault\")\n); =\n\nresult.Switch(\n  onFailure: () =\u003e Console.WriteLine(\"Fault is present\"),\n  onSuccess: () =\u003e Console.WriteLine(\"There is no fault\")\n);\n```\n\n### OnSome\n```csharp\nOptional\u003cint\u003e optional = ...;\n\noptional.OnSome(value =\u003e Console.WriteLine($\"Value is {value}\"));\noptional.OnSome(() =\u003e Console.WriteLine(\"Value is present\"));\n```\n\n### OnNone\n```csharp\nOptional\u003cint\u003e optional = ...;\n\noptional.OnNone(() =\u003e Console.WriteLine(\"There is no value\"));\n```\n\n### OnSuccess\n```csharp\nResult\u003cException, int\u003e result = ...;\n\nresult.OnSuccess(value =\u003e Console.WriteLine($\"Value is {value}\"));\nresult.OnSuccess(() =\u003e Console.WriteLine(\"Success\"));\n```\n\n```csharp\nResult\u003cException\u003e result = ...;\n\nresult.OnSuccess(() =\u003e Console.WriteLine(\"Success\"));\n```\n\n### OnFailure\n```csharp\nResult\u003cException, string\u003e result = ...;\n\nresult.OnFailure(fault =\u003e Console.WriteLine($\"Fault is {fault.Message}\"));\nresult.OnFailure(() =\u003e Console.WriteLine(\"Failure\"));\n```\n\n```csharp\nResult\u003cException\u003e result = ...;\n\nresult.OnFailure(fault =\u003e Console.WriteLine($\"Fault is {fault.Message}\"));\nresult.OnFailure(() =\u003e Console.WriteLine(\"Failure\"));\n```\n\n### Switch/OnSome/OnNone/OnSuccess/OnFailure method chaining\n```csharp\nOptional\u003cint\u003e optional = ...;\n\nstring result = optional\n  .Switch(\n    onNone: () =\u003e Console.WriteLine(\"There is no value\"),\n    onSome: value =\u003e Console.WriteLine($\"Value is {value}\"))\n  .OnSome(value =\u003e Console.WriteLine($\"Value is {value}\"))\n  .OnNone(() =\u003e Console.WriteLine(\"There is no value\"))\n  .Match(onNoneValue: \"valueOnNone\", onSome: value =\u003e value.ToString());\n```\n\n`Result\u003cTFault, TValue\u003e` and `Result\u003cTFault\u003e` have similar syntax.\n\n### Switch/OnSome/OnNone/OnSuccess/OnFailure return value upcasting\n\n```csharp\nOptional\u003cstring\u003e optional = ...;\n\nOptional\u003cobject\u003e upcasted = optional.Switch\u003cobject\u003e(\n  onNone: () =\u003e Console.WriteLine(\"There is no value\"),\n  onSome: value =\u003e Console.WriteLine($\"Value is {value}\")\n);\nOptional\u003cobject\u003e upcasted = optional.Switch\u003cobject\u003e(\n  onNone: () =\u003e Console.WriteLine(\"There is no value\"),\n  onSome: () =\u003e Console.WriteLine(\"Value is present\")\n);\n\nOptional\u003cobject\u003e upcasted = optional.OnSome\u003cobject\u003e(value =\u003e Console.WriteLine($\"Value is {value}\"));\nOptional\u003cobject\u003e upcasted = optional.OnSome\u003cobject\u003e(() =\u003e Console.WriteLine(\"Value is present\"));\n\nOptional\u003cobject\u003e upcasted = optional.OnNone\u003cobject\u003e(() =\u003e Console.WriteLine(\"There is no value\"));\n```\n\n`Result\u003cTFault, TValue\u003e` and `Result\u003cTFault\u003e` have similar syntax.\n\n### GetValueOrElse\n```csharp\nOptional\u003cstring\u003e optional = ...;\n\nstring extracted = optional.GetValueOrElse(() =\u003e \"defaultValue\");\nstring extracted = optional.GetValueOrElse(\"defaultValue\");\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eExamples with upcast\u003c/summary\u003e\n\n```csharp\nobject upcasted = optional.GetValueOrElse(() =\u003e new object());\nobject upcasted = optional.GetValueOrElse(new object());\n\nobject upcasted = optional.GetValueOrElse\u003cobject\u003e(() =\u003e new Exception(\"There is no value\"));\nobject upcasted = optional.GetValueOrElse\u003cobject\u003e(new Exception(\"There is no value\"));\n\nOptional\u003cobject\u003e objectOptional = ...;\nobject upcasted = objectOptional.GetValueOrElse(() =\u003e \"defaultValue\");\nobject upcasted = objectOptional.GetValueOrElse(\"defaultValue\");\n```\n\u003c/details\u003e\n\n\n```csharp\nResult\u003cException, string\u003e result = ...;\n\nstring extracted = result.GetValueOrElse(fault =\u003e $\"Converted to success fault: {fault.Message}\");\nstring extracted = result.GetValueOrElse(() =\u003e \"defaultValue\");\nstring extracted = result.GetValueOrElse(\"defaultValue\");\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eExamples with upcast\u003c/summary\u003e\n\n```csharp\nobject upcasted = result.GetValueOrElse(_ =\u003e new object());\nobject upcasted = result.GetValueOrElse(() =\u003e new object());\nobject upcasted = result.GetValueOrElse(new object());\n\nobject upcasted = result.GetValueOrElse\u003cobject\u003e(fault =\u003e new Exception(fault.Message));\nobject upcasted = result.GetValueOrElse\u003cobject\u003e(() =\u003e new Exception(\"There is no value\"));\nobject upcasted = result.GetValueOrElse\u003cobject\u003e(new Exception(\"There is no value\"));\n\nResult\u003cException, object\u003e objectResult = ...;\nobject upcasted = objectResult.GetValueOrElse(fault =\u003e fault.Message);\nobject upcasted = objectResult.GetValueOrElse(() =\u003e \"defaultValue\");\nobject upcasted = objectResult.GetValueOrElse(\"defaultValue\");\n```\n\u003c/details\u003e\n\n\n### GetFaultOrElse\n```csharp\nResult\u003cException, string\u003e result = ...;\n\nException extracted = result.GetFaultOrElse(value =\u003e new Exception(value));\nException extracted = result.GetFaultOrElse(() =\u003e new Exception());\nException extracted = result.GetFaultOrElse(new Exception());\n```\n\u003cdetails\u003e\n  \u003csummary\u003eExamples with upcast\u003c/summary\u003e\n\n```csharp\nobject upcasted = result.GetFaultOrElse(_ =\u003e new object());\nobject upcasted = result.GetFaultOrElse(() =\u003e new object());\nobject upcasted = result.GetFaultOrElse(new object());\n\nobject upcasted = result.GetFaultOrElse\u003cobject\u003e(value =\u003e value);\nobject upcasted = result.GetFaultOrElse\u003cobject\u003e(() =\u003e \"There is no fault\");\nobject upcasted = result.GetFaultOrElse\u003cobject\u003e(\"There is no fault\");\n\nResult\u003cobject, string\u003e objectResult = ...;\nobject upcasted = objectResult.GetFaultOrElse(value =\u003e value);\nobject upcasted = objectResult.GetFaultOrElse(() =\u003e \"defaultFault\");\nobject upcasted = objectResult.GetFaultOrElse(\"defaultFault\");\n```\n\u003c/details\u003e\n\n```csharp\nResult\u003cException\u003e result = ...;\n\nException extracted = result.GetFaultOrElse(() =\u003e new Exception());\nException extracted = result.GetFaultOrElse(new Exception());\n```\n\u003cdetails\u003e\n  \u003csummary\u003eExamples with upcast\u003c/summary\u003e\n\n```csharp\nobject upcasted = result.GetFaultOrElse(() =\u003e new object());\nobject upcasted = result.GetFaultOrElse(new object());\n\nobject upcasted = result.GetFaultOrElse\u003cobject\u003e(() =\u003e \"There is no fault\");\nobject upcasted = result.GetFaultOrElse\u003cobject\u003e(\"There is no fault\");\n\nResult\u003cobject\u003e objectResult = ...;\nobject upcasted = objectResult.GetFaultOrElse(() =\u003e \"defaultFault\");\nobject upcasted = objectResult.GetFaultOrElse(\"defaultFault\");\n```\n\u003c/details\u003e\n\n### GetValueOrThrow\n```csharp\nOptional\u003cstring\u003e optional = ...;\n\nstring extracted = optional.GetValueOrThrow(); // Throws `ValueMissingException` on None\nstring extracted = optional.GetValueOrThrow(new Exception(\"There is no value\"));\nstring extracted = optional.GetValueOrThrow(() =\u003e new Exception(\"There is no value\"));\n\nobject upcasted = optional.GetValueOrThrow\u003cobject\u003e();\nobject upcasted = optional.GetValueOrThrow\u003cobject\u003e(new Exception(\"There is no value\"));\nobject upcasted = optional.GetValueOrThrow\u003cobject\u003e(() =\u003e new Exception(\"There is no value\"));\n```\n\n```csharp\nResult\u003cException, string\u003e result = ...;\n\nstring extracted = result.GetValueOrThrow(); // Throws `ResultFailedException\u003cException\u003e` on Failure\nstring extracted = result.GetValueOrThrow(new Exception(\"There is no value\"));\nstring extracted = result.GetValueOrThrow(() =\u003e new Exception(\"There is no value\"));\nstring extracted = result.GetValueOrThrow(fault =\u003e new Exception(fault.Message));\n\nobject upcasted = result.GetValueOrThrow\u003cobject\u003e();\nobject upcasted = result.GetValueOrThrow\u003cobject\u003e(new Exception(\"There is no value\"));\nobject upcasted = result.GetValueOrThrow\u003cobject\u003e(() =\u003e new Exception(\"There is no value\"));\nobject upcasted = result.GetValueOrThrow\u003cobject\u003e(fault =\u003e new Exception(fault.Message));\n```\n\nTo override exception thrown by default for a specific `TValue` you can implement an extension method with the specific `TValue` in your namespace. You can also use [inheritance](#inheritance) to override exception thrown by default for `TValue` in any namespace.\n\u003cdetails\u003e\n  \u003csummary\u003eExample\u003c/summary\u003e\n\n```csharp\nnamespace CustomValues\n{\n  class CustomValue\n  {\n  }\n  static class GetValueOrThrowExtensions\n  {\n    static CustomValue GetValueOrThrow(this Optional\u003cCustomValue\u003e optional)\n    {\n      return optional.GetValueOrThrow(new Exception(\"Overiden!\"));\n    }\n\n    static CustomValue GetValueOrThrow\u003cTFault\u003e(this Result\u003cTFault, CustomValue\u003e result)\n    {\n      return result.GetValueOrThrow(new Exception(\"Overiden!\"));\n    }\n  }\n}\n```\n\u003c/details\u003e\n\n### GetFaultOrThrow\n```csharp\nResult\u003cException, string\u003e result = ...;\n\nException extracted = result.GetFaultOrThrow(); // Throws `ResultSucceedException\u003cstring\u003e` on Success\nException extracted = result.GetFaultOrThrow(new Exception(\"There is no fault\"));\nException extracted = result.GetFaultOrThrow(() =\u003e new Exception(\"There is no fault\"));\nException extracted = result.GetFaultOrThrow(value =\u003e new Exception(value));\n\nobject upcasted = result.GetFaultOrThrow\u003cobject\u003e();\nobject upcasted = result.GetFaultOrThrow\u003cobject\u003e(new Exception(\"There is no fault\"));\nobject upcasted = result.GetFaultOrThrow\u003cobject\u003e(() =\u003e new Exception(\"There is no fault\"));\nobject upcasted = result.GetFaultOrThrow\u003cobject\u003e(value =\u003e new Exception(value));\n```\n\n```csharp\nResult\u003cException\u003e result = ...;\n\nException extracted = result.GetFaultOrThrow(); // Throws `ResultSucceedException` on Success\nException extracted = result.GetFaultOrThrow(new Exception(\"There is no fault\"));\nException extracted = result.GetFaultOrThrow(() =\u003e new Exception(\"There is no fault\"));\n\nobject upcasted = result.GetFaultOrThrow\u003cobject\u003e();\nobject upcasted = result.GetFaultOrThrow\u003cobject\u003e(new Exception(\"There is no fault\"));\nobject upcasted = result.GetFaultOrThrow\u003cobject\u003e(() =\u003e new Exception(\"There is no fault\"));\n```\n\nTo override exception thrown by default exception for a specific `TFault` you can implement an extension method with the specific `TFault` in your namespace. You can also use [inheritance](#inheritance) to override exception thrown by default for `TFault` in any namespace.\n\u003cdetails\u003e\n  \u003csummary\u003eExample\u003c/summary\u003e\n\n```csharp\nnamespace CustomFaults\n{\n  class CustomFault\n  {\n  }\n  static class GetValueOrThrowExtensions\n  {\n    static CustomFault GetFaultOrThrow(this Result\u003cCustomFault\u003e result)\n    {\n      return result.GetFaultOrThrow(new Exception(\"Overridden!\"));\n    }\n\n    static CustomFault GetFaultOrThrow\u003cTValue\u003e(this Result\u003cCustomFault, TValue\u003e result)\n    {\n      return result.GetFaultOrThrow(new Exception(\"Overridden!\"));\n    }\n  }\n}\n```\n\u003c/details\u003e\n\n### GetValueOrDefault\n```csharp\nOptional\u003cstring\u003e optional = ...;\n\nstring? extracted = optional.GetValueOrDefault(); // null or actual value for reference types\n\nobject? upcasted = optional.GetValueOrDefault\u003cobject\u003e();\n```\n\n```csharp\nOptional\u003cint\u003e optional = ...;\n\nint extracted = optional.GetValueOrDefault();  // 0 or actual value for the value type\n```\n\n```csharp\nResult\u003cException, string\u003e result = ...;\n\nstring? extracted = result.GetValueOrDefault(); // null or actual value for reference types\n\nobject? upcasted = result.GetValueOrDefault\u003cobject\u003e();\n```\n\n```csharp\nResult\u003cException, int\u003e result = ...;\n\nint extracted = result.GetValueOrDefault();  // 0 or actual value for the value type\n```\n\n### GetFaultOrDefault\n```csharp\nResult\u003cException, string\u003e result = ...;\n\nException? extracted = result.GetFaultOrDefault(); // null or actual fault for reference types\n\nobject? upcasted = result.GetFaultOrDefault\u003cobject\u003e();\n```\n\n```csharp\nResult\u003cint, string\u003e result = ...;\n\nint extracted = result.GetFaultOrDefault();  // 0 or actual fault for the value type\n```\n\n```csharp\nResult\u003cException\u003e result = ...;\n\nException? extracted = result.GetFaultOrDefault(); // null or actual fault for reference types\n\nobject? upcasted = result.GetFaultOrDefault\u003cobject\u003e();\n```\n\n```csharp\nResult\u003cint\u003e result = ...;\n\nint extracted = result.GetFaultOrDefault();  // 0 or actual fault for the value type\n```\n\n### GetValueOrNull\nThis method can be applied to non-nullable value types (structs) only.\n\n```csharp\nOptional\u003cint\u003e optional = ...;\n\nint? extracted = optional.GetValueOrNull(); // null or actual value\n```\n\n```csharp\nResult\u003cException, int\u003e result = ...;\n\nint? extracted = result.GetValueOrNull(); // null or actual value\n```\n\nUpcasts are not supported.\n\n### GetFaultOrNull\nThis method can be applied to non-nullable value types (structs) only.\n\n```csharp\nResult\u003cint, string\u003e result = ...;\n\nint? extracted = result.GetFaultOrNull(); // null or actual fault\n```\n\n```csharp\nResult\u003cint\u003e result = ...;\n\nint? extracted = result.GetFaultOrNull(); // null or actual fault\n```\n\nUpcasts are not supported.\n\n### EnsureHasValue\n```csharp\nOptional\u003cstring\u003e optional = ...;\n\n// Nothing if `Some`\noptional.EnsureHasValue(); // Throws `ValueMissingException` on None\noptional.EnsureHasValue(new Exception(\"There is no value\"));\noptional.EnsureHasValue(() =\u003e new Exception(\"There is no value\"))\n```\n\nTo override exception thrown by default exception for a specific `TValue` you can implement an extension method with the specific `TValue` in your namespace. You can also use [inheritance](#inheritance) to override exception thrown by default for `TValue` in any namespace.\n\u003cdetails\u003e\n  \u003csummary\u003eExample\u003c/summary\u003e\n\n```csharp\nnamespace Custom\n{\n  class CustomValue\n  {\n  }\n  static class EnsureHasValueExtensions\n  {\n    static void EnsureHasValue(this Optional\u003cCustomValue\u003e optional)\n    {\n      return optional.EnsureHasValue(new Exception(\"Overridden!\"));\n    }\n  }\n}\n```\n\u003c/details\u003e\n\n### EnsureNone\n```csharp\nOptional\u003cstring\u003e optional = ...;\n\n// Nothing if `None`\noptional.EnsureNone(); // Throws `ValueExistsException\u003cstring\u003e` if `Some`\noptional.EnsureNone(new Exception(\"There is value\"));\noptional.EnsureNone(() =\u003e new Exception(\"There is value\"))\noptional.EnsureNone(value =\u003e new Exception($\"There is value: {value}\"))\n```\n\nTo override exception thrown by default exception for a specific `TValue` you can implement an extension method with the specific `TValue` in your namespace. You can also use [inheritance](#inheritance) to override exception thrown by default for `TValue` in any namespace.\n\u003cdetails\u003e\n  \u003csummary\u003eExample\u003c/summary\u003e\n\n```csharp\nnamespace Custom\n{\n  class CustomValue\n  {\n  }\n  static class EnsureNoneExtensions\n  {\n    static void EnsureNone(this Optional\u003cCustomValue\u003e optional)\n    {\n      return optional.EnsureNone(new Exception(\"Overridden!\"));\n    }\n  }\n}\n```\n\u003c/details\u003e\n\n### EnsureSuccess\n```csharp\nResult\u003cException, string\u003e result = ...;\n\n// Nothing if `Success`\nresult.EnsureSuccess(); // Throws `ResultFailedException\u003cException\u003e` on Failure\nresult.EnsureSuccess(new Exception(\"There is no value\"));\nresult.EnsureSuccess(() =\u003e new Exception(\"There is no value\"))\nresult.EnsureSuccess(fault =\u003e new Exception(fault.Message))\n```\n\n```csharp\nResult\u003cException\u003e result = ...;\n\n// Nothing if `Success`\nresult.EnsureSuccess(); // Throws `ResultFailedException\u003cException\u003e` on Failure\nresult.EnsureSuccess(new Exception(\"It's failure\"));\nresult.EnsureSuccess(() =\u003e new Exception(\"It's failure\"))\nresult.EnsureSuccess(fault =\u003e new Exception(fault.Message))\n```\n\nTo override exception thrown by default exception for a specific `TValue` or `TFault` you can implement an extension method with the specific `TValue` or `TFault` in your namespace. You can also use [inheritance](#inheritance) to override exception thrown by default for `TFault` or `TValue` in any namespace.\n\u003cdetails\u003e\n  \u003csummary\u003eExample\u003c/summary\u003e\n\n```csharp\nnamespace CustomTypes\n{\n  class CustomFault\n  {\n  }\n  class CustomValue\n  {\n  }\n  static class EnsureSuccessExtensions\n  {\n    static void EnsureSuccess\u003cTFault\u003e(this Result\u003cTFault, CustomValue\u003e result)\n    {\n      return result.EnsureSuccess(new Exception(\"Overridden!\"));\n    }\n    static void EnsureSuccess(this Result\u003cCustomFault\u003e result)\n    {\n      return result.EnsureSuccess(new Exception(\"Overridden!\"));\n    }\n  }\n}\n```\n\u003c/details\u003e\n\n### EnsureFailure\n```csharp\nResult\u003cException, string\u003e result = ...;\n\n// Nothing if `Failure`\nresult.EnsureFailure(); // Throws `ResultSucceedException\u003cstring\u003e` on Success\nresult.EnsureFailure(new Exception(\"There is no fault\"));\nresult.EnsureFailure(() =\u003e new Exception(\"There is no fault\"))\nresult.EnsureFailure(value =\u003e new Exception(value))\n```\n\n```csharp\nResult\u003cException\u003e result = ...;\n\n// Nothing if `Failure`\nresult.EnsureFailure(); // Throws `ResultSucceedException` on Success\nresult.EnsureFailure(new Exception(\"It's success\"));\nresult.EnsureFailure(() =\u003e new Exception(\"It's success\"))\n```\n\nTo override exception thrown by default exception for a specific `TValue` or `TFault` you can implement an extension method with the specific `TValue` or `TFault` in your namespace. You can also use [inheritance](#inheritance) to override exception thrown by default for `TFault`or `TValue` in any namespace.\n\u003cdetails\u003e\n  \u003csummary\u003eExample\u003c/summary\u003e\n\n```csharp\nnamespace CustomTypes\n{\n  class CustomFault\n  {\n  }\n  class CustomValue\n  {\n  }\n  static class EnsureFailureExtensions\n  {\n    static void EnsureFailure\u003cTFault\u003e(this Result\u003cTFault, CustomValue\u003e result)\n    {\n      return result.EnsureFailure(new Exception(\"Overridden!\"));\n    }\n    static void EnsureFailure(this Result\u003cCustomFault\u003e result)\n    {\n      return result.EnsureFailure(new Exception(\"Overridden!\"));\n    }\n  }\n}\n```\n\u003c/details\u003e\n\n\n### HasSome\n```csharp\nOptional\u003cstring\u003e optional = \"has value\";\n\nbool extracted = optional.HasSome; // true\n```\n\n```csharp\nOptional\u003cstring\u003e optional = Optional.None();\n\nbool extracted = optional.HasSome; // false\n```\n\n### IsNone\n```csharp\nOptional\u003cstring\u003e optional = \"has value\";\n\nbool extracted = optional.IsNone; // false\n```\n\n```csharp\nOptional\u003cstring\u003e optional = Optional.None();\n\nbool extracted = optional.IsNone; // true\n```\n\n### Success\n```csharp\nResult\u003cException, string\u003e result = \"has value\";\n\nbool extracted = result.Success; // true\n```\n\n```csharp\nResult\u003cException, string\u003e result = new Exception();\n\nbool extracted = result.Success; // false\n```\n\n```csharp\nResult\u003cException\u003e result = Result.Succeed();\n\nbool extracted = result.Success; // true\n```\n\n```csharp\nResult\u003cException\u003e result = new Exception();\n\nbool extracted = result.Success; // false\n```\n\n### Failure\n```csharp\nResult\u003cException, string\u003e result = \"has value\";\n\nbool extracted = result.Failure; // false\n```\n\n```csharp\nResult\u003cException, string\u003e result = new Exception();\n\nbool extracted = result.Failure; // true\n```\n\n```csharp\nResult\u003cException\u003e result = Result.Succeed();\n\nbool extracted = result.Failure; // false\n```\n\n```csharp\nResult\u003cException\u003e result = new Exception();\n\nbool extracted = result.Failure; // true\n```\n\n### LINQ method syntax (GetValues, GetFaults)\n```csharp\nOptional\u003cstring\u003e optional = ...;\n\n// `[]` if `None`\n// `[value]` if `Some`\nIEnumerable\u003cstring\u003e values = optional\n  .GetValues()\n  .ToArray(); // optional\n\nIEnumerable\u003cobject\u003e upcasted = optional.GetValues\u003cobject\u003e();\n```\n\n```csharp\nResult\u003cException, string\u003e result = ...;\n\n// `[]` if `Failure`\n// `[value]` if `Success`\nIEnumerable\u003cstring\u003e values = result.GetValues().ToArray();\n\nIEnumerable\u003cobject\u003e upcasted = result.GetValues\u003cobject\u003e();\n```\n\n```csharp\nResult\u003cException, string\u003e result = ...;\n\n// `[exception]` if `Failure`\n// `[]` if `Success`\nIEnumerable\u003cException\u003e faults = result.GetFaults().ToArray();\n\nIEnumerable\u003cobject\u003e upcasted = result.GetFaults\u003cobject\u003e();\n```\n\n```csharp\nResult\u003cException\u003e result = ...;\n\n// `[exception]` if `Failure`\n// `[]` if `Success`\nIEnumerable\u003cException\u003e faults = result.GetFaults().ToArray();\n\nIEnumerable\u003cobject\u003e upcasted = result.GetFaults\u003cobject\u003e();\n```\n\n### LINQ query syntax\n\nThere is no preferred way of combining the `IEnumerable` and `Optional` or `Result`.\nYou can choose a variant that suits your needs and implement it in your project.\nSome variants are found in the tests folder.\n\nSome examples:\n\n#### Threat `Result` and `Optional` as containers with single or no elements\n\nThis is the simplest variant. But using it results in losing fault details.\n\n##### Optional\n```csharp\nOptional\u003cint\u003e optional = Optional.Some(10);\n\nIEnumerable\u003cint\u003e extracted =\n  from value in optional\n  from i1 in new [] { 1, 2 }\n  from i2 in new [] { 100, 200 }\n  select value + i1 + i2;\n\nIEnumerable\u003cint\u003e extracted =\n  from i1 in new [] { 1, 2 }\n  from value in optional\n  from i2 in new [] { 100, 200 }\n  select i1 + value + i2;\n\n// extracted is [111, 112, 211, 212].\n```\n\n```csharp\nOptional\u003cint\u003e optional = Optional.Some(10);\n\nIEnumerable\u003cint\u003e extracted =\n  from value in optional\n  from i1 in new [] { 1, 2 }\n  from i2 in Array.Empty\u003cint\u003e()\n  select value + i1 + i2;\n\nIEnumerable\u003cint\u003e extracted =\n  from i1 in new [] { 1, 2 }\n  from value in optional\n  from i2 in Array.Empty\u003cint\u003e()\n  select i1 + value + i2;\n\n// extracted is empty.\n```\n\n```csharp\nOptional\u003cint\u003e optional = Optional.None();\n\nIEnumerable\u003cint\u003e extracted =\n  from value in optional\n  from i in new [] { 1, 2 }\n  select value + i;\n\nIEnumerable\u003cint\u003e extracted =\n  from i in new [] { 1, 2 }\n  from value in optional\n  select value + i;\n\n// extracted is empty.\n\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eTo implement it you can use the code\u003c/summary\u003e\n\n```csharp\npublic static IEnumerable\u003cTResult\u003e SelectMany\u003cTValue, TItem, TResult\u003e(\n  this IOptional\u003cTValue\u003e optional,\n  Func\u003cTValue, IEnumerable\u003cTItem\u003e\u003e collectionSelector,\n  Func\u003cTValue, TItem, TResult\u003e resultSelector)\n{\n  return optional.GetValues().SelectMany(collectionSelector, resultSelector);\n}\n\npublic static IEnumerable\u003cTResult\u003e SelectMany\u003cTItem, TValue, TResult\u003e(\n  this IEnumerable\u003cTItem\u003e collection,\n  Func\u003cTItem, IOptional\u003cTValue\u003e\u003e optionSelector,\n  Func\u003cTItem, TValue, TResult\u003e resultSelector)\n{\n  return collection.SelectMany(value =\u003e optionSelector(value).GetValues(), resultSelector);\n}\n```\n\u003c/details\u003e\n\n##### Result\n```csharp\nResult\u003cException, int\u003e result = Result.Succeed(10);\n\nIEnumerable\u003cint\u003e extracted =\n  from value in result\n  from i1 in new [] { 1, 2 }\n  from i2 in new [] { 100, 200 }\n  select value + i1 + i2;\n\nIEnumerable\u003cint\u003e extracted =\n  from i1 in new [] { 1, 2 }\n  from value in result\n  from i2 in new [] { 100, 200 }\n  select i1 + value + i2;\n\n// extracted is [111, 112, 211, 212].\n```\n\n```csharp\nResult\u003cException, int\u003e result = Result.Succeed(10);\n\nIEnumerable\u003cint\u003e extracted =\n  from value in result\n  from i1 in new [] { 1, 2 }\n  from i2 in Array.Empty\u003cint\u003e()\n  select value + i1 + i2;\n\nIEnumerable\u003cint\u003e extracted =\n  from i1 in new [] { 1, 2 }\n  from value in result\n  from i2 in Array.Empty\u003cint\u003e()\n  select i1 + value + i2;\n\n// extracted is empty.\n```\n\n```csharp\nResult\u003cException, int\u003e result = Result.Fail(new Exception());\n\nIEnumerable\u003cint\u003e extracted =\n  from value in result\n  from i in new [] { 1, 2 }\n  select value + i;\n\nIEnumerable\u003cint\u003e extracted =\n  from i in new [] { 1, 2 }\n  from value in result\n  select value + i;\n\n// extracted is empty.\n\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eTo implement it you can use the code\u003c/summary\u003e\n\n```csharp\npublic static IEnumerable\u003cTResult\u003e SelectMany\u003cTFault, TValue, TItem, TResult\u003e(\n  this IResult\u003cTFault, TValue\u003e result,\n  Func\u003cTValue, IEnumerable\u003cTItem\u003e\u003e collectionSelector,\n  Func\u003cTValue, TItem, TResult\u003e resultSelector)\n{\n  return result.GetValues().SelectMany(collectionSelector, resultSelector);\n}\n\npublic static IEnumerable\u003cTResult\u003e SelectMany\u003cTItem, TFault, TValue, TResult\u003e(\n  this IEnumerable\u003cTItem\u003e collection,\n  Func\u003cTItem, IResult\u003cTFault, TValue\u003e\u003e selector,\n  Func\u003cTItem, TValue, TResult\u003e resultSelector)\n{\n  return collection.SelectMany(value =\u003e selector(value).GetValues(), resultSelector);\n}\n```\n\u003c/details\u003e\n\n#### Returning the first found fault\n\nThis is is the most useful way of combining data.\n\n##### Optional\n\n```csharp\nOptional\u003cint\u003e optional = Optional.Some(10);\n\nOptional\u003cIEnumerable\u003cint\u003e\u003e extracted =\n  from value in optional\n  from i1 in new [] { 1, 2 }\n  from i2 in new [] { 100, 200 }\n  select value + i1 + i2;\n\nOptional\u003cIEnumerable\u003cint\u003e\u003e extracted =\n  from i1 in new [] { 1, 2 }\n  from value in optional\n  from i2 in new [] { 100, 200 }\n  select i1 + value + i2;\n\n// extracted is [111, 112, 211, 212].\n```\n\n```csharp\nOptional\u003cint\u003e optional = Optional.Some(10);\n\nOptional\u003cIEnumerable\u003cint\u003e\u003e extracted =\n  from value in optional\n  from i1 in new [] { 1, 2 }\n  from i2 in Array.Empty\u003cint\u003e()\n  select value + i1 + i2;\n\nOptional\u003cIEnumerable\u003cint\u003e\u003e extracted =\n  from i1 in new [] { 1, 2 }\n  from value in optional\n  from i2 in Array.Empty\u003cint\u003e()\n  select i1 + value + i2;\n\n// extracted is empty.\n```\n\n```csharp\nOptional\u003cint\u003e optional = Optional.None();\n\nOptional\u003cIEnumerable\u003cint\u003e\u003e extracted =\n  from value in optional\n  from i in new [] { 1, 2 }\n  select value + i;\n\nOptional\u003cIEnumerable\u003cint\u003e\u003e extracted =\n  from i in new [] { 1, 2 }\n  from value in optional\n  select value + i;\n\n// extracted is `None`.\n\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eTo implement it, four `SelectMany` methods can be used\u003c/summary\u003e\n\n```csharp\nstatic Optional\u003cIEnumerable\u003cTResult\u003e\u003e SelectMany\u003cTItem, TValue, TResult\u003e(\n  this IEnumerable\u003cTItem\u003e collection,\n  Func\u003cTItem, Optional\u003cTValue\u003e\u003e optionalSelector,\n  Func\u003cTItem, TValue, TResult\u003e resultSelector)\n{\n  List\u003cTResult\u003e results = new();\n  foreach (var item in collection)\n  {\n    if (!optionalSelector(item).TryGetValue(out var value))\n      return Optional.None();\n    results.Add(resultSelector(item, value));\n  }\n  return results;\n}\n\nstatic Optional\u003cIEnumerable\u003cTResult\u003e\u003e SelectMany\u003cTItem1, TItem2, TResult\u003e(\n  this Optional\u003cIEnumerable\u003cTItem1\u003e\u003e optional,\n  Func\u003cTItem1, IEnumerable\u003cTItem2\u003e\u003e collectionSelector,\n  Func\u003cTItem1, TItem2, TResult\u003e resultSelector) =\u003e\n  optional.MapValue(values =\u003e values.SelectMany(value =\u003e collectionSelector(value).Select(item =\u003e resultSelector(value, item))));\n\nstatic Optional\u003cIEnumerable\u003cTResult\u003e\u003e SelectMany\u003cTValue, TItem, TResult\u003e(\n  this Optional\u003cIEnumerable\u003cTValue\u003e\u003e optional,\n  Func\u003cTValue, Optional\u003cTItem\u003e\u003e collectionSelector,\n  Func\u003cTValue, TItem, TResult\u003e resultSelector) =\u003e\n  optional.Match(\n    Optional\u003cIEnumerable\u003cTResult\u003e\u003e.None,\n    values =\u003e SelectMany(values, collectionSelector, resultSelector));\n\n// To allow infinite chaining the following method could be placed in local namespace and other 3 methods can be placed in root namespace\nstatic Optional\u003cIEnumerable\u003cTResult\u003e\u003e SelectMany\u003cTValue, TItem, TResult\u003e(\n  this Optional\u003cTValue\u003e optional,\n  Func\u003cTValue, IEnumerable\u003cTItem\u003e\u003e collectionSelector,\n  Func\u003cTValue, TItem, TResult\u003e resultSelector) =\u003e\n  optional.MapValue(value =\u003e collectionSelector(value).Select(item =\u003e resultSelector(value, item)));\n```\n\u003c/details\u003e\n\n##### Result\n```csharp\nResult\u003cException, int\u003e result = Result.Succeed(10);\n\nResult\u003cException, IEnumerable\u003cint\u003e\u003e extracted =\n  from value in result\n  from i1 in new [] { 1, 2 }\n  from i2 in new [] { 100, 200 }\n  select value + i1 + i2;\n\nResult\u003cException, IEnumerable\u003cint\u003e\u003e extracted =\n  from i1 in new [] { 1, 2 }\n  from value in result\n  from i2 in new [] { 100, 200 }\n  select i1 + value + i2;\n\n// extracted is [111, 112, 211, 212].\n```\n\n```csharp\nResult\u003cException, int\u003e result = Result.Succeed(10);\n\nResult\u003cException, IEnumerable\u003cint\u003e\u003e extracted =\n  from value in result\n  from i1 in new [] { 1, 2 }\n  from i2 in Array.Empty\u003cint\u003e()\n  select value + i1 + i2;\n\nResult\u003cException, IEnumerable\u003cint\u003e\u003e extracted =\n  from i1 in new [] { 1, 2 }\n  from value in result\n  from i2 in Array.Empty\u003cint\u003e()\n  select i1 + value + i2;\n\n// extracted is empty.\n```\n\n```csharp\nResult\u003cException, int\u003e result = Result.Fail(new Exception(\"fault\"));\n\nResult\u003cException, IEnumerable\u003cint\u003e\u003e extracted =\n  from value in result\n  from i in new [] { 1, 2 }\n  select value + i;\n\nResult\u003cException, IEnumerable\u003cint\u003e\u003e extracted =\n  from i in new [] { 1, 2 }\n  from value in result\n  select value + i;\n\n// extracted is Exception(\"fault\").\n\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eTo implement it, four `SelectMany` methods can be used\u003c/summary\u003e\n\n```csharp\nstatic Result\u003cTFault, IEnumerable\u003cTResult\u003e\u003e SelectMany\u003cTItem, TFault, TValue, TResult\u003e(\n  this IEnumerable\u003cTItem\u003e collection,\n  Func\u003cTItem, Result\u003cTFault, TValue\u003e\u003e selector,\n  Func\u003cTItem, TValue, TResult\u003e resultSelector)\n{\n  List\u003cTResult\u003e results = new();\n  foreach (var item in collection)\n  {\n    if (selector(item).TryGetFault(out var fault, out var value))\n      return fault;\n    results.Add(resultSelector(item, value));\n  }\n  return results;\n}\n\nstatic Result\u003cTFault, IEnumerable\u003cTResult\u003e\u003e SelectMany\u003cTFault, TItem1, TItem2, TResult\u003e(\n  this Result\u003cTFault, IEnumerable\u003cTItem1\u003e\u003e result,\n  Func\u003cTItem1, IEnumerable\u003cTItem2\u003e\u003e collectionSelector,\n  Func\u003cTItem1, TItem2, TResult\u003e resultSelector) =\u003e\n  result.MapValue(values =\u003e values.SelectMany(value =\u003e collectionSelector(value).Select(item =\u003e resultSelector(value, item))));\n\nstatic Result\u003cTFault, IEnumerable\u003cTResult\u003e\u003e SelectMany\u003cTFault, TValue, TItem, TResult\u003e(\n  this Result\u003cTFault, IEnumerable\u003cTValue\u003e\u003e result,\n  Func\u003cTValue, Result\u003cTFault, TItem\u003e\u003e collectionSelector,\n  Func\u003cTValue, TItem, TResult\u003e resultSelector) =\u003e\n  result.Match(\n    Result\u003cTFault, IEnumerable\u003cTResult\u003e\u003e.Fail,\n    values =\u003e SelectMany(values, collectionSelector, resultSelector));\n\n// To allow infinite chaining the following method could be placed in local namespace and other 3 methods can be placed in root namespace\nstatic Result\u003cTFault, IEnumerable\u003cTResult\u003e\u003e SelectMany\u003cTFault, TValue, TItem, TResult\u003e(\n            this Result\u003cTFault, TValue\u003e result,\n            Func\u003cTValue, IEnumerable\u003cTItem\u003e\u003e collectionSelector,\n            Func\u003cTValue, TItem, TResult\u003e resultSelector) =\u003e\n            result.MapValue(value =\u003e collectionSelector(value).Select(item =\u003e resultSelector(value, item)));\n```\n\u003c/details\u003e\n\n### foreach\n```csharp\nstring FindValue(Optional\u003cint\u003e optional)\n{\n  foreach(var value in optional)\n  {\n    return value + \" is found!\";\n  }\n\n  return \"no value found\";\n}\n\n```\n\n```csharp\nstring FindValue(Result\u003cException, int\u003e result)\n{\n  foreach(var value in result)\n  {\n    return value + \" is found!\";\n  }\n\n  return \"no value found\";\n}\n\n```\n\n### ToString\n```csharp\nOptional\u003cstring\u003e optional = ...;\n\n// `None\u003cstring\u003e` if `None`\n// `Some\u003cstring\u003e value={Value}` if `Some`\nstring str = optional.ToString();\n```\n\n```csharp\nResult\u003cint, string\u003e result = ...;\n\n// `ResultFailure\u003cInt32, string\u003e fault={Fault}` if `Failure`\n// `ResultSuccess\u003cInt32, string\u003e value={Value}` if `Success`\nstring str = result.ToString();\n```\n\n```csharp\nResult\u003cint\u003e result = ...;\n\n// `ResultFailure\u003cInt32\u003e fault={Fault}` if `Failure`\n// `ResultSuccess\u003cInt32\u003e` if `Success`\nstring str = result.ToString();\n```\n\n### Upcasts\n\nYou can upcast a return value of many data extraction methods by providing a type argument or by combining two arguments of different types in a single method call.\n\nExamples:\n```csharp\nOptional\u003cstring\u003e optional = ...\n\nOptional\u003cobject\u003e upcasted1 = optional.OnNone\u003cobject\u003e(str =\u003e Console.WriteLine(str));\nOptional\u003cobject\u003e upcasted2 = optional.Match(onNone: () =\u003e new object(), onSome: str =\u003e str);\n```\n\nOnly safe upcasts are allowed.\nFor example, `Optional\u003cstring\u003e` can be converted to `Optional\u003cobject\u003e` but not vice versa.\n\nSafety is enforced by covariance rules. So:\n* Upcasts are only supported for reference types because covariance can not be used with value types.\n* Upcasts are only supported for synchronous methods because `Task\u003cT\u003e` and `ValueTask\u003cT\u003e` types do not support covariance.\n\n\n## Conversion of generic arguments\n\nAll conversion methods except `Upcast` method support async extensions for every listed synchronous scenario.\nAll synchronous methods support upcasts of `TFault` and `TValue`.\n\nAsync extensions make use of methods returning `Task\u003cT\u003e`, `ValueTask\u003cT\u003e` and inline async lambdas. For example:\n```csharp\nasync Task\u003cint\u003e Get1(int number) =\u003e number + 1;\nasync ValueTask\u003cint\u003e Get2(number) =\u003e number - 1;\n\nTask\u003cOptional\u003cint\u003e\u003e Get(Task\u003cOptional\u003cint\u003e\u003e optional)\n{\n  return optional\n    .MapValue(i =\u003e Get1(i))\n    .MapValue(i =\u003e Get2(i))\n    .MapValue(async i =\u003e await Get1(i));\n}\n```\n\nIf there is at least one async method in a chain returning `Task\u003cT\u003e` the result is `Task\u003cT2\u003e`. Otherwise, the result is `ValueTask\u003cT2\u003e`.\n\n### MapValue\n\n`MapValue` changes value or/and type of `TValue`.\n\n```csharp\nOptional\u003cstring\u003e optional = ...;\n\nOptional\u003cstring\u003e extracted = optional.MapValue(str =\u003e str + \"suffix\");\nOptional\u003cstring\u003e extracted = optional.MapValue(() =\u003e \"new value\");\nOptional\u003cstring\u003e extracted = optional.MapValue(\"other string\");\n\nOptional\u003cint\u003e extracted = optional.MapValue(str =\u003e int.Parse(str));\nOptional\u003cint\u003e extracted = optional.MapValue(() =\u003e int.Parse(\"123\"));\nOptional\u003cint\u003e extracted = optional.MapValue(15);\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eAsync examples\u003c/summary\u003e\n\n```csharp\nOptional\u003cstring\u003e optional = ...;\n\nValueTask\u003cOptional\u003cstring\u003e\u003e extracted = optional.MapValue(async str =\u003e await Task.FromResult(str));\nValueTask\u003cOptional\u003cstring\u003e\u003e extracted = optional.MapValue(str =\u003e new ValueTask(str));\nTask\u003cOptional\u003cstring\u003e\u003e extracted = optional.MapValue(str =\u003e Task.FromResult(str));\n```\n\n```csharp\nValueTask\u003cOptional\u003cstring\u003e\u003e optional = ...;\n\nValueTask\u003cOptional\u003cstring\u003e\u003e extracted = optional.MapValue(str =\u003e str + \"suffix\");\nValueTask\u003cOptional\u003cstring\u003e\u003e extracted = optional.MapValue(async str =\u003e await Task.FromResult(str));\nValueTask\u003cOptional\u003cstring\u003e\u003e extracted = optional.MapValue(str =\u003e new ValueTask(str));\nTask\u003cOptional\u003cstring\u003e\u003e extracted = optional.MapValue(str =\u003e Task.FromResult(str));\n```\n\n```csharp\nTask\u003cOptional\u003cstring\u003e\u003e optional = ...;\n\nTask\u003cOptional\u003cstring\u003e\u003e extracted = optional.MapValue(str =\u003e str + \"suffix\");\nTask\u003cOptional\u003cstring\u003e\u003e extracted = optional.MapValue(async str =\u003e await Task.FromResult(str));\nTask\u003cOptional\u003cstring\u003e\u003e extracted = optional.MapValue(str =\u003e new ValueTask(str));\nTask\u003cOptional\u003cstring\u003e\u003e extracted = optional.MapValue(str =\u003e Task.FromResult(str));\n```\n\u003c/details\u003e\n\n```csharp\nResult\u003cGuid, string\u003e result = ...;\n\nResult\u003cGuid, string\u003e extracted = result.MapValue(str =\u003e str + \"suffix\");\nResult\u003cGuid, string\u003e extracted = result.MapValue(() =\u003e \"new value\");\nResult\u003cGuid, string\u003e extracted = result.MapValue(\"other string\");\n\nResult\u003cGuid, int\u003e extracted = result.MapValue(str =\u003e int.Parse(str));\nResult\u003cGuid, int\u003e extracted = result.MapValue(() =\u003e int.Parse(\"123\"));\nResult\u003cGuid, int\u003e extracted = result.MapValue(15);\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eAsync examples\u003c/summary\u003e\n\n```csharp\nResult\u003cGuid, string\u003e result = ...;\n\nValueTask\u003cResult\u003cGuid, string\u003e\u003e extracted = result.MapValue(async str =\u003e await Task.FromResult(str));\nValueTask\u003cResult\u003cGuid, string\u003e\u003e extracted = result.MapValue(str =\u003e new ValueTask(str));\nTask\u003cResult\u003cGuid, string\u003e\u003e extracted = result.MapValue(str =\u003e Task.FromResult(str));\n```\n\n```csharp\nValueTask\u003cResult\u003cGuid, string\u003e\u003e result = ...;\n\nValueTask\u003cResult\u003cGuid, string\u003e\u003e extracted = result.MapValue(str =\u003e str + \"suffix\");\nValueTask\u003cResult\u003cGuid, string\u003e\u003e extracted = result.MapValue(async str =\u003e await Task.FromResult(str));\nValueTask\u003cResult\u003cGuid, string\u003e\u003e extracted = result.MapValue(str =\u003e new ValueTask(str));\nTask\u003cResult\u003cGuid, string\u003e\u003e extracted = result.MapValue(str =\u003e Task.FromResult(str));\n```\n\n```csharp\nTask\u003cResult\u003cGuid, string\u003e\u003e result = ...;\n\nTask\u003cResult\u003cGuid, string\u003e\u003e extracted = result.MapValue(str =\u003e str + \"suffix\");\nTask\u003cResult\u003cGuid, string\u003e\u003e extracted = result.MapValue(async str =\u003e await Task.FromResult(str));\nTask\u003cResult\u003cGuid, string\u003e\u003e extracted = result.MapValue(str =\u003e new ValueTask(str));\nTask\u003cResult\u003cGuid, string\u003e\u003e extracted = result.MapValue(str =\u003e Task.FromResult(str));\n```\n\u003c/details\u003e\n\n### MapFault\n\n`MapFault` changes value or/and type of `TFault`.\n\n```csharp\nResult\u003cstring, Guid\u003e result = ...;\n\nResult\u003cstring, Guid\u003e extracted = result.MapFault(str =\u003e str + \"suffix\");\nResult\u003cstring, Guid\u003e extracted = result.MapFault(() =\u003e \"new fault\");\nResult\u003cstring, Guid\u003e extracted = result.MapFault(\"other string\");\n\nResult\u003cint, Guid\u003e extracted = result.MapFault(str =\u003e int.Parse(str));\nResult\u003cint, Guid\u003e extracted = result.MapFault(() =\u003e int.Parse(\"123\"));\nResult\u003cint, Guid\u003e extracted = result.MapFault(15);\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eAsync examples\u003c/summary\u003e\n\n```csharp\nResult\u003cstring, Guid\u003e result = ...;\n\nValueTask\u003cResult\u003cstring, Guid\u003e\u003e extracted = result.MapFault(async str =\u003e await Task.FromResult(str));\nValueTask\u003cResult\u003cstring, Guid\u003e\u003e extracted = result.MapFault(str =\u003e new ValueTask(str));\nTask\u003cResult\u003cstring, Guid\u003e\u003e extracted = result.MapFault(str =\u003e Task.FromResult(str));\n```\n\n```csharp\nValueTask\u003cResult\u003cstring, Guid\u003e\u003e result = ...;\n\nValueTask\u003cResult\u003cstring, Guid\u003e\u003e extracted = result.MapFault(str =\u003e str + \"suffix\");\nValueTask\u003cResult\u003cstring, Guid\u003e\u003e extracted = result.MapFault(async str =\u003e await Task.FromResult(str));\nValueTask\u003cResult\u003cstring, Guid\u003e\u003e extracted = result.MapFault(str =\u003e new ValueTask(str));\nTask\u003cResult\u003cstring, Guid\u003e\u003e extracted = result.MapFault(str =\u003e Task.FromResult(str));\n```\n\n```csharp\nTask\u003cResult\u003cstring, Guid\u003e\u003e result = ...;\n\nTask\u003cResult\u003cstring, Guid\u003e\u003e extracted = result.MapFault(str =\u003e str + \"suffix\");\nTask\u003cResult\u003cstring, Guid\u003e\u003e extracted = result.MapFault(async str =\u003e await Task.FromResult(str));\nTask\u003cResult\u003cstring, Guid\u003e\u003e extracted = result.MapFault(str =\u003e new ValueTask(str));\nTask\u003cResult\u003cstring, Guid\u003e\u003e extracted = result.MapFault(str =\u003e Task.FromResult(str));\n```\n\u003c/details\u003e\n\n```csharp\nResult\u003cstring\u003e result = ...;\n\nResult\u003cstring\u003e extracted = result.MapFault(str =\u003e str + \"suffix\");\nResult\u003cstring\u003e extracted = result.MapFault(() =\u003e \"new fault\");\nResult\u003cstring\u003e extracted = result.MapFault(\"other string\");\n\nResult\u003cint\u003e extracted = result.MapFault(str =\u003e int.Parse(str));\nResult\u003cint\u003e extracted = result.MapFault(() =\u003e int.Parse(\"123\"));\nResult\u003cint\u003e extracted = result.MapFault(15);\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eAsync examples\u003c/summary\u003e\n\n```csharp\nResult\u003cstring\u003e result = ...;\n\nValueTask\u003cResult\u003cstring\u003e\u003e extracted = result.MapFault(async str =\u003e await Task.FromResult(str));\nValueTask\u003cResult\u003cstring\u003e\u003e extracted = result.MapFault(str =\u003e new ValueTask(str));\nTask\u003cResult\u003cstring\u003e\u003e extracted = result.MapFault(str =\u003e Task.FromResult(str));\n```\n\n```csharp\nValueTask\u003cResult\u003cstring\u003e\u003e result = ...;\n\nValueTask\u003cResult\u003cstring\u003e\u003e extracted = result.MapFault(str =\u003e str + \"suffix\");\nValueTask\u003cResult\u003cstring\u003e\u003e extracted = result.MapFault(async str =\u003e await Task.FromResult(str));\nValueTask\u003cResult\u003cstring\u003e\u003e extracted = result.MapFault(str =\u003e new ValueTask(str));\nTask\u003cResult\u003cstring\u003e\u003e extracted = result.MapFault(str =\u003e Task.FromResult(str));\n```\n\n```csharp\nTask\u003cResult\u003cstring\u003e\u003e result = ...;\n\nTask\u003cResult\u003cstring\u003e\u003e extracted = result.MapFault(str =\u003e str + \"suffix\");\nTask\u003cResult\u003cstring\u003e\u003e extracted = result.MapFault(async str =\u003e await Task.FromResult(str));\nTask\u003cResult\u003cstring\u003e\u003e extracted = result.MapFault(str =\u003e new ValueTask(str));\nTask\u003cResult\u003cstring\u003e\u003e extracted = result.MapFault(str =\u003e Task.FromResult(str));\n```\n\u003c/details\u003e\n\n### Upcast\n\n```csharp\nOptional\u003cstring\u003e optional = ...;\n\n// Compiles\nOptional\u003cobject\u003e objectOptional = optional.Upcast\u003cobject\u003e();\n\n// Does not compile\nvar doesNotCompile = objectOptional.Upcast\u003cstring\u003e();\n```\n\n```csharp\nResult\u003cstring\u003e result = ...;\n\n// Compiles\nResult\u003cobject\u003e objectResult = result.Upcast\u003cobject\u003e();\n\n// Does not compile\nvar doesNotCompile = objectResult.Upcast\u003cstring\u003e();\n```\n\n```csharp\nResult\u003cstring, string\u003e result = ...;\n\n// Compiles\nResult\u003cobject, string\u003e objectResult1 = result.Upcast\u003cobject, string\u003e();\nResult\u003cstring, object\u003e objectResult2 = result.Upcast\u003cstring, string\u003e();\nResult\u003cobject, object\u003e objectResult3 = result.Upcast\u003cobject, object\u003e();\n\n// Does not compile\nvar doesNotCompile = objectResult1.Upcast\u003cstring, string\u003e();\nvar doesNotCompile = objectResult2.Upcast\u003cstring, string\u003e();\nvar doesNotCompile = objectResult3.Upcast\u003cstring, string\u003e();\n```\n\nAsync extensions are not supported `Upcast` methods.\n\n\n## Result combining\n\nThere are some monadic extensions that can help you to reduce lines and errors in your code.\nAll `Optional`/`Result` combining methods support async extensions for every listed synchronous scenario.\n\nCurrently synchronous `Optional`/`Result` combining methods do not support upcasts of `TFault` and `TValue`.\n\n\n### Then\n\n`Then` is `Then` (`And`, `ContinueWith`, `ContinueOnSome`, `Bind`) `Result` combining method.\n\nIf a first optional/result is `None`/`Failure` then the `None`/`Failure` is returned.\nIf the first optional/result is `Some`/`Success` then a second optional/result is returned.\nThe second `Optional`/`Result` factory method is only executed if the first `Optional`/`Result` is `Some`/`Success`.\n\n`TFault` types should be identical. Upcasts are not supported yet.\n`TValue` types can be different.\n\n```csharp\nOptional\u003cint\u003e optional1 = ...;\nOptional\u003cstring\u003e optional2 = ...;\n\n// If optional1 is None then None is returned.\n// Otherwise optional2 is returned.\nOptional\u003cstring\u003e result = optional1.Then(optional2);\nOptional\u003cstring\u003e result = optional1.Then(() =\u003e optional2);\nOptional\u003cstring\u003e result = optional1.Then(i =\u003e i \u003e 10 ? Optional\u003cstring\u003e.Some(i.ToString()) : Optional\u003cstring\u003e.None());\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eAsync examples\u003c/summary\u003e\n\n```csharp\nOptional\u003cint\u003e optional1 = ...;\nOptional\u003cstring\u003e optional2 = ...;\n\nValueTask\u003cOptional\u003cstring\u003e\u003e result = optional1.Then(async value =\u003e await Task.FromResult(optional2));\nValueTask\u003cOptional\u003cstring\u003e\u003e result = optional1.Then(value =\u003e new ValueTask(optional2));\nTask\u003cOptional\u003cstring\u003e\u003e result = optional1.Then(value =\u003e Task.FromResult(optional2));\n\nValueTask\u003cOptional\u003cstring\u003e\u003e result = new ValueTask(optional1).Then(value =\u003e optional2);\nValueTask\u003cOptional\u003cstring\u003e\u003e result = new ValueTask(optional1).Then(async value =\u003e await Task.FromResult(optional2));\nValueTask\u003cOptional\u003cstring\u003e\u003e result = new ValueTask(optional1).Then(value =\u003e new ValueTask(optional2));\nTask\u003cOptional\u003cstring\u003e\u003e result = new ValueTask(optional1).Then(value =\u003e Task.FromResult(optional2));\n\nTask\u003cOptional\u003cstring\u003e\u003e result = Task.FromResult(optional1).Then(value =\u003e optional2);\nTask\u003cOptional\u003cstring\u003e\u003e result = Task.FromResult(optional1).Then(async value =\u003e await Task.FromResult(optional2));\nTask\u003cOptional\u003cstring\u003e\u003e result = Task.FromResult(optional1).Then(value =\u003e new ValueTask(optional2));\nTask\u003cOptional\u003cstring\u003e\u003e result = Task.FromResult(optional1).Then(value =\u003e Task.FromResult(optional2));\n```\n\u003c/details\u003e\n\n```csharp\nResult\u003cException, int\u003e result1 = ...;\nResult\u003cException, string\u003e result2 = ...;\n\n// If option1 is None then None is returned.\n// Otherwise option2 is returned.\nResult\u003cException, string\u003e result = result1.Then(result2);\nResult\u003cException, string\u003e result = result1.Then(() =\u003e result2);\nResult\u003cException, string\u003e result = result1.Then(i =\u003e i \u003e 10 ? Result\u003cException, string\u003e.Success(i.ToString()) : Result\u003cException, string\u003e.Failure());\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eAsync examples\u003c/summary\u003e\n\n```csharp\nResult\u003cException, int\u003e result1 = ...;\nResult\u003cException, string\u003e result2 = ...;\n\nValueTask\u003cResult\u003cException, string\u003e\u003e result = result1.Then(async value =\u003e await Task.FromResult(result2));\nValueTask\u003cResult\u003cException, string\u003e\u003e result = result1.Then(value =\u003e new ValueTask(result2));\nTask\u003cResult\u003cException, string\u003e\u003e result = result1.Then(value =\u003e Task.FromResult(result2));\n\nValueTask\u003cResult\u003cException, string\u003e\u003e result = new ValueTask(result1).Then(value =\u003e result2);\nValueTask\u003cResult\u003cException, string\u003e\u003e result = new ValueTask(result1).Then(async value =\u003e await Task.FromResult(result2));\nValueTask\u003cResult\u003cException, string\u003e\u003e result = new ValueTask(result1).Then(value =\u003e new ValueTask(result2));\nTask\u003cResult\u003cException, string\u003e\u003e result = new ValueTask(result1).Then(value =\u003e Task.FromResult(result2));\n\nTask\u003cResult\u003cException, string\u003e\u003e result = Task.FromResult(result1).Then(value =\u003e result2);\nTask\u003cResult\u003cException, string\u003e\u003e result = Task.FromResult(result1).Then(async value =\u003e await Task.FromResult(result2));\nTask\u003cResult\u003cException, string\u003e\u003e result = Task.FromResult(result1).Then(value =\u003e new ValueTask(result2));\nTask\u003cResult\u003cException, string\u003e\u003e result = Task.FromResult(result1).Then(value =\u003e Task.FromResult(result2));\n```\n\u003c/details\u003e\n\nAll meaningful combinations of `Optional\u003cTValue\u003e`, `Result\u003cTFault\u003e` and `Result\u003cTFault, TValue\u003e` are also supported.\n\n### OrElse\n\n`OrElse` is `Or` (`OrElse`, `Else`, `Catch`, `ContinueOnNone`) `Result` combining method.\n\nIf a first optional/result is `Some`/`Success` then it is returned.\nIf the first optional/result is `None`/`Failure` then a second optional/result is returned.\nThe second `Optional`/`Result` factory method is only executed if the first `Optional`/`Result` is `None`/`Failure`.\n\n`TValue` types should be identical. Upcasts are not supported yet.\n`TFault` types can be different.\n\n\n```csharp\nOptional\u003cstring\u003e optional1 = ...;\nOptional\u003cstring\u003e optional2 = ...;\n\n// If optional1 is Some then option1 is returned.\n// Otherwise optional2 is returned.\nOptional\u003cstring\u003e result = optional1.OrElse(optional2);\nOptional\u003cstring\u003e result = optional1.OrElse(() =\u003e optional2);\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eAsync examples\u003c/summary\u003e\n\n```csharp\nOptional\u003cstring\u003e optional1 = ...;\nOptional\u003cstring\u003e optional2 = ...;\n\nValueTask\u003cOptional\u003cstring\u003e\u003e result = optional1.OrElse(async () =\u003e await Task.FromResult(optional2));\nValueTask\u003cOptional\u003cstring\u003e\u003e result = optional1.OrElse(() =\u003e new ValueTask(optional2));\nTask\u003cOptional\u003cstring\u003e\u003e result = optional1.OrElse(() =\u003e Task.FromResult(optional2));\n\nValueTask\u003cOptional\u003cstring\u003e\u003e result = new ValueTask(optional1).OrElse(() =\u003e optional2);\nValueTask\u003cOptional\u003cstring\u003e\u003e result = new ValueTask(optional1).OrElse(async () =\u003e await Task.FromResult(optional2));\nValueTask\u003cOptional\u003cstring\u003e\u003e result = new ValueTask(optional1).OrElse(() =\u003e new ValueTask(optional2));\nTask\u003cOptional\u003cstring\u003e\u003e result = new ValueTask(optional1).OrElse(() =\u003e Task.FromResult(optional2));\n\nTask\u003cOptional\u003cstring\u003e\u003e result = Task.FromResult(optional1).OrElse(() =\u003e optional2);\nTask\u003cOptional\u003cstring\u003e\u003e result = Task.FromResult(optional1).OrElse(async () =\u003e await Task.FromResult(optional2));\nTask\u003cOptional\u003cstring\u003e\u003e result = Task.FromResult(optional1).OrElse(() =\u003e new ValueTask(optional2));\nTask\u003cOptional\u003cstring\u003e\u003e result = Task.FromResult(optional1).OrElse(() =\u003e Task.FromResult(optional2));\n```\n\u003c/details\u003e\n\n```csharp\nResult\u003cint, string\u003e result1 = ...;\nResult\u003cException, string\u003e result2 = ...;\n\n// If option1 is Some then option1 is returned.\n// Otherwise option2 is returned.\nResult\u003cException, string\u003e result = result1.OrElse(result2);\nResult\u003cException, string\u003e result = result1.OrElse(() =\u003e result2);\nResult\u003cException, string\u003e result = result1.OrElse(fault =\u003e result2);\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eAsync examples\u003c/summary\u003e\n\n```csharp\nResult\u003cint, string\u003e result1 = ...;\nResult\u003cException, string\u003e result2 = ...;\n\nValueTask\u003cResult\u003cException, string\u003e\u003e result = result1.OrElse(async fault =\u003e await Task.FromResult(result2));\nValueTask\u003cResult\u003cException, string\u003e\u003e result = result1.OrElse(fault =\u003e new ValueTask(result2));\nTask\u003cResult\u003cException, string\u003e\u003e result = result1.OrElse(fault =\u003e Task.FromResult(result2));\n\nValueTask\u003cResult\u003csException, tring\u003e\u003e result = new ValueTask(result1).OrElse(fault =\u003e result2);\nValueTask\u003cResult\u003csException, tring\u003e\u003e result = new ValueTask(result1).OrElse(async fault =\u003e await Task.FromResult(result2));\nValueTask\u003cResult\u003cException, string\u003e\u003e result = new ValueTask(result1).OrElse(fault =\u003e new ValueTask(result2));\nTask\u003cResult\u003cException, string\u003e\u003e result = new ValueTask(result1).OrElse(fault =\u003e Task.FromResult(result2));\n\nTask\u003cResult\u003cException, string\u003e\u003e result = Task.FromResult(result1).OrElse(fault =\u003e result2);\nTask\u003cResult\u003cException, string\u003e\u003e result = Task.FromResult(result1).OrElse(async fault =\u003e await Task.FromResult(result2));\nTask\u003cResult\u003cException, string\u003e\u003e result = Task.FromResult(result1).OrElse(fault =\u003e new ValueTask(result2));\nTask\u003cResult\u003cException, string\u003e\u003e result = Task.FromResult(result1).OrElse(fault =\u003e Task.FromResult(result2));\n```\n\u003c/details\u003e\n\nAll meaningful combinations of `Optional\u003cTValue\u003e`, `Result\u003cTFault\u003e` and `Result\u003cTFault, TValue\u003e` are also supported.\n\n### Then/OrElse method chaining\n\n```csharp\nabstract Optional\u003cstring\u003e GetFormLogin();\nabstract Optional\u003cGuid\u003e GetUser(string login);\nabstract Task\u003cOptional\u003cGuid\u003e\u003e CreateUser(string login);\nabstract Optional\u003cDateTime\u003e GetCreationDate(Guid userId);\n\nTask\u003cOptional\u003clong\u003e\u003e userCreationDateTicks =\n   GetFormLogin()\n  .Then(login =\u003e GetUser(login).OrElse(() =\u003e CreateUser(login)))\n  .Then(userId =\u003e GetCreationDate(userId))\n  .MapValue(date =\u003e date.Ticks);\n```\n\n```csharp\nabstract Result\u003cTicksError, string\u003e GetFormLogin();\nabstract Result\u003cUserException, Guid\u003e GetUser(string login);\nabstract Task\u003cResult\u003cTicksError, Guid\u003e\u003e CreateUser(string login);\nabstract Result\u003cTicksError, DateTime\u003e GetCreationDate(Guid userId);\nabstract Result\u003cTicksError\u003e EnsureTicksIsValid(long ticks);\n\nTask\u003cResult\u003cGetTicksError\u003e\u003e userCreationDateTicksValid =\n   GetFormLogin()\n  .Then(login =\u003e GetUser(login).OrElse(() =\u003e CreateUser(login)))\n  .Then(userId =\u003e GetCreationDate(userId))\n  .MapValue(date =\u003e date.Ticks);\n  .Then(ticks =\u003e EnsureTicksIsValid(ticks))\n```\n\n### Select\n\n`Select` is a mix of `MapValue` and `Then`.\nLike both of them, a factory method of a second `Optional`/`Result` or value is only executed if the first `Optional`/`Result` is `Some`/`Success`.\nLike `MapValue` it allows changing type and value by using value factory.\nUnlike `MapValue` and like `Then` it allows creating a second `Optional`/`Result` which is a result of the whole operation.\nIt also allows you to change `Some`/`Success` to `None`/`Failure` if you want.\n\n`TFault` types should be identical. Upcasts are not supported yet.\n`TValue` types can be different.\n\n\u003cdetails\u003e\n  \u003csummary\u003eOptional examples\u003c/summary\u003e\n\n```csharp\nOptional\u003cstring\u003e optional = ...;\n\nOptional\u003cstring\u003e extracted = optional.Select(str =\u003e str.Length \u003e 5 ? Optional.Some(str) : Optional.None());\nOptional\u003cstring\u003e extracted = optional.Select(str =\u003e str + \"suffix\");\nOptional\u003cint\u003e extracted = optional.Select(str =\u003e int.Parse(str));\n\nValueTask\u003cOptional\u003cint\u003e\u003e extracted = optional.Select(async str =\u003e await Task.FromResult(int.Parse(str)));\nValueTask\u003cOptional\u003cint\u003e\u003e extracted = optional.Select(str =\u003e new ValueTask(int.Parse(str)));\nTask\u003cOptional\u003cint\u003e\u003e extracted = optional.Select(str =\u003e Task.FromResult(int.Parse(str)));\n\nValueTask\u003cOptional\u003cint\u003e\u003e extracted = new ValueTask(optional).Select(async str =\u003e await Task.FromResult(int.Parse(str)));\nValueTask\u003cOptional\u003cint\u003e\u003e extracted = new ValueTask(optional).Select(str =\u003e new ValueTask(int.Parse(str)));\nTask\u003cOptional\u003cint\u003e\u003e extracted = new ValueTask(optional).Select(str =\u003e Task.FromResult(int.Parse(str)));\n\nTask\u003cOptional\u003cint\u003e\u003e extracted = Task.FromResult(optional).Select(async str =\u003e await Task.FromResult(int.Parse(str)));\nTask\u003cOptional\u003cint\u003e\u003e extracted = Task.FromResult(optional).Select(str =\u003e new ValueTask(int.Parse(str)));\nTask\u003cOptional\u003cint\u003e\u003e extracted = Task.FromResult(optional).Select(str =\u003e Task.FromResult(int.Parse(str)));\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eResult examples\u003c/summary\u003e\n\n```csharp\nResult\u003cException, string\u003e result = ...;\n\nResult\u003cException, string\u003e extracted = result.Select(str =\u003e str.Length \u003e 5 ? Result\u003cException, string\u003e.Succeed(str) : Result\u003cException, string\u003e.Fail(new Exception(str)));\nResult\u003cException, string\u003e extracted = result.Select(str =\u003e str + \"suffix\");\nResult\u003cException, int\u003e extracted = result.Select(str =\u003e int.Parse(str));\n\nValueTask\u003cOptional\u003cint\u003e\u003e extracted = result.Select(async str =\u003e await Task.FromResult(int.Parse(str)));\nValueTask\u003cOptional\u003cint\u003e\u003e extracted = result.Select(str =\u003e new ValueTask(int.Parse(str)));\nTask\u003cOptional\u003cint\u003e\u003e extracted = result.Select(str =\u003e Task.FromResult(int.Parse(str)));\n\nValueTask\u003cOptional\u003cint\u003e\u003e extracted = new ValueTask(result).Select(str =\u003e int.Parse(str));\nValueTask\u003cOptional\u003cint\u003e\u003e extracted = new ValueTask(result).Select(async str =\u003e await Task.FromResult(int.Parse(str)));\nValueTask\u003cOptional\u003cint\u003e\u003e extracted = new ValueTask(result).Select(str =\u003e new ValueTask(int.Parse(str)));\nTask\u003cOptional\u003cint\u003e\u003e extracted = new ValueTask(result).Select(str =\u003e Task.FromResult(int.Parse(str)));\n\nTask\u003cOptional\u003cint\u003e\u003e extracted = Task.FromResult(result).Select(str =\u003e int.Parse(str));\nTask\u003cOptional\u003cint\u003e\u003e extracted = Task.FromResult(result).Select(async str =\u003e await Task.FromResult(int.Parse(str)));\nTask\u003cOptional\u003cint\u003e\u003e extracted = Task.FromResult(result).Select(str =\u003e new ValueTask(int.Parse(str)));\nTask\u003cOptional\u003cint\u003e\u003e extracted = Task.FromResult(result).Select(str =\u003e Task.FromResult(int.Parse(str)));\n```\n\u003c/details\u003e\n\n### Do notation\n```csharp\nabstract Optional\u003cGuid\u003e GetCurrentUserId();\nabstract Optional\u003cint\u003e GetCurrentIndex();\nabstract Optional\u003cProduct\u003e GetCurrentProduct();\nabstract Optional\u003cstring\u003e GetMessage(Guid userId, int index, Product product);\nabstract Optional\u003cConvertResult\u003e Convert(string message, Product product);\n\nOptional\u003cConvertResult\u003e result =\n  from userId  in GetCurrentUserId()\n  where userId != Guid.Empty\n  from index   in GetCurrentIndex()\n  from product in GetCurrentProduct()\n  let nextIndex = index + 1\n  from message in GetMessage(userId, nextIndex, product)\n  select Convert(message, product);\n\n```\nThe last `select` expression can return either `Optional\u003cTResult\u003e` or just `TResult`.\n\n```csharp\nabstract Result\u003cException, Guid\u003e GetCurrentUserId();\nabstract Result\u003cException\u003e EnsureUserIdIsCorrect(Guid userId);\nabstract Result\u003cException, int\u003e GetCurrentIndex();\nabstract Result\u003cException, Product\u003e GetCurrentProduct();\nabstract Result\u003cint, string\u003e GetMessage(Guid userId, int index, Product product);\nabstract Result\u003cException, ConvertResult\u003e Convert(string message, Product product);\n\nResult\u003cException, ConvertResult\u003e result =\n  from userId  in GetCurrentUserId()\n  where EnsureUserIdIsCorrect(userId)\n  from index   in GetCurrentIndex()\n  from product in GetCurrentProduct()\n  let nextIndex = index + 1\n  from message in GetMessage(userId, nextIndex, product).MapFault(i =\u003e new Exception(i.ToString()))\n  select Convert(message, product);\n\n```\nThe last `select` expression can return `Result\u003cException, TResult\u003e`, `Result\u003cException\u003e` or just `TResult`.\n`TFault` should be identical in all clauses. Use `MapFault` to convert different `TFault` to the same one.\n\n### Do notation with async extensions\n```csharp\nabstract Optional\u003cGuid\u003e GetCurrentUserId();\nabstract Task\u003cint\u003e GetCurrentIndex();\nabstract ValueTask\u003cOptional\u003cProduct\u003e\u003e GetCurrentProduct();\nabstract Task\u003cOptional\u003cstring\u003e\u003e GetMessage(Guid userId, int index, Product product);\nabstract Task\u003cFormat\u003e GetFormat(int index, string message);\nabstract Optional\u003cConvertResult\u003e Convert(string message, Format format);\nabstract Task\u003cbool\u003e IsValid(int index);\n\nTask\u003cOptional\u003cConvertResult\u003e\u003e result =\n  from userId  in GetCurrentUserId() // A\n  where userId != Guid.Empty       // B\n  from index   in GetCurrentIndex() // C\n  from product in GetCurrentProduct() // D\n  let nextIndex = index + 1\n  where IsValid(nextIndex) // E\n  from message in GetMessage(userId, nextIndex, product) // F\n  from format  in GetFormat(nextIndex, message) // G\n  select Convert(message, format); // H\n\n```\nWhere:\n* `A` (first `from`/`in` clause) must return `Optional\u003cT\u003e`, `ValueTask\u003cOptional\u003cT\u003e\u003e` or `Task\u003cOptional\u003cT\u003e\u003e`.\n* `B` and `E` (`where` clause) may return `bool`, `ValueTask\u003cbool\u003e` or `Task\u003cbool\u003e`.\n* `C`, `D`, `F` and `G`  (subsequent `from`/`in` clause) may return one of `Optional\u003cT\u003e`, `ValueTask\u003cT\u003e`, `ValueTask\u003cOptional\u003cT\u003e\u003e`, `Task\u003cT\u003e` or `Task\u003cOptional\u003cT\u003e\u003e`. Subsequent expressions may depend on previous expressions (`F` and `G` for example) or may not depend on previous expressions (`C` and `D` for example). The total count of `B`, `C`, `D`, `E`, `F` and `G`-like statements is efficiently unlimited.\n* `H` (`select` clause) should return  `TResult`, `Optional\u003cTResult\u003e`, `ValueTask\u003cTResult\u003e`, `ValueTask\u003cOptional\u003cTResult\u003e\u003e`, `Task\u003cTResult\u003e` or `Task\u003cOptional\u003cTResult\u003e\u003e`.\n\n```csharp\nabstract Result\u003cException, Guid\u003e GetCurrentUserId();\nabstract Result\u003cException\u003e EnsureUserIdIsCorrect(Guid userId);\nabstract Task\u003cint\u003e GetCurrentIndex();\nabstract ValueTask\u003cResult\u003cException, Product\u003e\u003e GetCurrentProduct();\nabstract Task\u003cResult\u003cint, string\u003e\u003e GetMessage(Guid userId, int index, Product product);\nabstract Task\u003cFormat\u003e GetFormat(int index, string message);\nabstract Result\u003cException, ConvertResult\u003e Convert(string message, Format format);\nabstract Task\u003cResult\u003cException\u003e\u003e IsValid(int index);\n\nTask\u003cResult\u003cException, ConvertResult\u003e\u003e result =\n  from userId  in GetCurrentUserId() // A\n  where EnsureUserIdIsCorrect(userId) // B\n  from index   in GetCurrentIndex() // C\n  from product in GetCurrentProduct() // D\n  let nextIndex = index + 1\n  where IsValid(nextIndex) // E\n  from message in GetMessage(userId, nextIndex, product).MapFault(i =\u003e new Exception(i.ToString())) // F\n  from format  in GetFormat(nextIndex, message) // G\n  select Convert(message, format); // H\n```\n\nWhere:\n* `A` (first `from`/`in` clause) must return `Result\u003cTFault, TValue\u003e`, `ValueTask\u003cResult\u003cTFault, TValue\u003e\u003e` or `Task\u003cResult\u003cTFault, TValue\u003e\u003e`.\n* `B` and `E` (`where` clause) may return `Result\u003cTFault\u003e`, `ValueTask\u003cResult\u003cTFault\u003e\u003e` or `Task\u003cResult\u003cTFault\u003e\u003e`.\n* `C`, `D`, `F` and `G` (subsequent `from`/`in` clause) may return one of `Result\u003cTFault, TValue\u003e`, `ValueTask\u003cTValue\u003e`, `ValueTask\u003cResult\u003cTFault, TValue\u003e\u003e`, `Task\u003cTValue\u003e` or `Task\u003cResult\u003cTFault, TValue\u003e\u003e`. Subsequent expressions may depend on previous expressions (`F` and `G` for example) or may not depend on previous expressions (`C` and `D` for example). The total count of `B`, `C`, `D`, `E`, `F` and `G`-like statements is efficiently unlimited.\n* `H` (`select` clause) should return  `TResult`, `Result\u003cTFault\u003e`, `Result\u003cTFault, TResult\u003e`, `ValueTask\u003cTResult\u003e`, `ValueTask\u003cResult\u003cTFault\u003e\u003e`, `ValueTask\u003cResult\u003cTFault, TResult\u003e\u003e`, `Task\u003cTResult\u003e`, `Task\u003cResult\u003cTFault\u003e\u003e` or `Task\u003cResult\u003cTFault, TResult\u003e\u003e`.\n\n`TFault` should be identical in all clauses. Use `MapFault` to convert different `TFault` to the same one.\n\n\n## Inheritance\n\nYou can create your own `Result` type by inheriting provided types.\n\n```csharp\nclass StringFaultResult\u003cTValue\u003e : Result\u003cstring, TValue\u003e\n{\n  private readonly Result\u003cstring, TValue\u003e result;\n\n  public StringFaultResult(string fault) =\u003e result = Fail(fault);\n\n  public StringFaultResult(TValue value) =\u003e result = Succeed(value);\n\n  public override TResult Match\u003cTResult\u003e(Func\u003cstring, TResult\u003e onFailure, Func\u003cTValue, TResult\u003e onSuccess)\n    =\u003e result.Match(onFailure, onSuccess);\n}\n```\n\nAll synchronous methods are inherited.\n\nIf you inherit, to bring back some lost features you can reimplement the following:\n* implicit conversion operators\n* some async extensions that do not inherit by default due to invariance of `Task\u003cT\u003e` and `ValueTask\u003cT\u003e`\n\nBecause this implementation relies heavily on C# 9 source generators it is not a hard task to implement a new feature that reimplements lost features automatically.\nSend me requests if you need such a feature.\n\nYou can also override extensions methods. For example:\n* `MapValue` to override return type with inherited type\n* `GetValueOrThrow` to override Exception type thrown by default\n\n\n## Other\n\n* `Equals` and `GetHashCode` make use of type arguments, faults and values (if present) for calculations.\n* There is no `fold` method.\n\n\n## Yet to be implemented\n\n* (easy) Currently only `Result` combining methods (`Map`, `Select`, `Then`, `OrElse` and do notation), `MapValue` and `MapFault` support async extensions with `Task` or `ValueTask` types. Data extraction methods (like `TryGetValue`, `Switch` or `GetOrThrow`) only support synchronous execution.\n* (easy) Currently monadic extensions (`Select`, `Then`, `OrElse` and do notation) do not support upcasts for synchronous methods.\n* (medium) Implement do-notations (LINQ Query Syntax) for collections.\n* (medium) Currently implemented source generators can not generate async extensions and implicit conversion operators for custom inherited classes in your assemblies.\n* (hard) Do notation for `Result\u003cTFault, TValue\u003e` with different `TFault` type arguments is possible in a limited way but unimplemented. If it is implemented, it would disallow a few struct type arguments for `TFault` and would not enable all scenarios of selecting `Result\u003cTFaultOther\u003e` with different `TFault` argument in subsequent `from/in` clauses. The current workaround is to use `MapFault` method before passing `Result` to a do notation clause.\n\nSend me your requests if you need such features.\n\n\n## Contributing\n\nContributions are appreciated.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskbkontur%2Fresults","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskbkontur%2Fresults","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskbkontur%2Fresults/lists"}