{"id":25234531,"url":"https://github.com/lucasteles/resulteles","last_synced_at":"2025-10-26T10:30:27.670Z","repository":{"id":179040348,"uuid":"662795732","full_name":"lucasteles/Resulteles","owner":"lucasteles","description":"A practical Result data structure implementation for C#","archived":false,"fork":false,"pushed_at":"2024-04-01T14:20:25.000Z","size":75,"stargazers_count":4,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-04-27T05:03:22.126Z","etag":null,"topics":["csharp","dotnet","either","monad","result"],"latest_commit_sha":null,"homepage":"","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/lucasteles.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2023-07-05T23:02:35.000Z","updated_at":"2024-04-06T19:16:57.000Z","dependencies_parsed_at":"2023-12-11T06:52:52.894Z","dependency_job_id":"bfa2d190-fd54-47b0-8ea2-9dc7badefbfd","html_url":"https://github.com/lucasteles/Resulteles","commit_stats":null,"previous_names":["lucasteles/resulteles"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucasteles%2FResulteles","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucasteles%2FResulteles/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucasteles%2FResulteles/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucasteles%2FResulteles/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lucasteles","download_url":"https://codeload.github.com/lucasteles/Resulteles/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238306445,"owners_count":19450146,"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","dotnet","either","monad","result"],"created_at":"2025-02-11T13:59:49.529Z","updated_at":"2025-10-26T10:30:27.334Z","avatar_url":"https://github.com/lucasteles.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![CI](https://github.com/lucasteles/Resulteles/actions/workflows/ci.yml/badge.svg)](https://github.com/lucasteles/Resulteles/actions/workflows/ci.yml)\n[![Nuget](https://img.shields.io/nuget/v/Resulteles.svg?style=flat)](https://www.nuget.org/packages/Resulteles)\n![](https://raw.githubusercontent.com/lucasteles/Resulteles/badges/badge_linecoverage.svg)\n![](https://raw.githubusercontent.com/lucasteles/Resulteles/badges/badge_branchcoverage.svg)\n![](https://raw.githubusercontent.com/lucasteles/Resulteles/badges/test_report_badge.svg)\n![](https://raw.githubusercontent.com/lucasteles/Resulteles/badges/lines_badge.svg)\n\n![](https://raw.githubusercontent.com/lucasteles/Resulteles/badges/dotnet_version_badge.svg)\n![](https://img.shields.io/badge/Lang-C%23-green)\n![https://editorconfig.org/](https://img.shields.io/badge/style-EditorConfig-black)\n\n# Resulteles\n\n**Resulteles is a practical and lightweight library that define and facilitate the use of a `success|failure` data\nstructure called `Result` (aka `Either`).**\n\n## Getting started\n\n[NuGet package](https://www.nuget.org/packages/Resulteles) available:\n\n```ps\n$ dotnet add package Resulteles\n```\n\n### Creating Results\n\nYou can create any result using the static methods on `Result`\n\n```csharp\n// explicitly\nvar resultSuccess = Result.Ok\u003cint, string\u003e(42);\nvar resultError = Result.Error\u003cint, string\u003e(\"Something wrong!\");\n\nvar processResult = Result.Try(() =\u003e { return 1; });\nvar processAsyncResult = Result.TryAsync(async () =\u003e { return await Task.FromResult(2); });\n```\n\nIn most of the scenarios you will be using result as a return of a method or function, because of that it\nimplements implicit convert operators from the generic types, reducing the generic type definition noise\n\n```csharp\npublic Result\u003cint, string\u003e GetEvenNumber(int number)\n{\n    if (number % 2 is 0)\n        return number;\n    else\n        return $\"{number} is not even!\";\n}\n```\n\n### Reading Result Value\n\nThe `Result` type acts like a blackbox, by default there is no way to just get the typed value mostly because it can be\ntwo things, an `Ok` or an `Error`.\n\n```csharp\nResult\u003cint, string\u003e result = GetEvenNumber(2);\n\n// return -1 on error\nint value1 = result.Match(\n    n =\u003e n,\n    error =\u003e -1\n);\n\nresult.Switch(\n    n =\u003e Console.WriteLine($\"the number {n} is even\"),\n    error =\u003e Console.WriteLine(error)\n);\n\n// return 0 on error\nvar value2 = result.DefaultValue(0);\n\n// lazily define the bad case value\nvar value3 = result.DefaultWith(e =\u003e e.Length);\n\n// get the value or throw an exeption\nvar value4 = result.GetValueOrThrow();\n\n// try/out pattern\nif (result.TryGet(out var ok, out var error))\n    Console.WriteLine($\"the number {ok} is even\");\nelse\n    Console.WriteLine(error);\n```\n\n### Operators\n\nMost types you not even need to extract the value, you can just apply functions or combine with other `Result` types:\n\n```csharp\nvar result1 = Result.Ok\u003cint, string\u003e(1);\n\n// Map the result value only when it is Ok\nvar result2 = result1.Select(n =\u003e n + 1);\n\n// map for ok or error case\nResult\u003cstring, int\u003e result3 = result1.Select(n =\u003e n.ToString(), err =\u003e err.Length);\n\n// SelectMany / Bind / FlatMamap\n// Nested results transformation\nResult\u003cint, string\u003e resultCombined = result1.SelectMany(n =\u003e GetEvenNumber(n));\n\n// Zip Results together into a tuple\n// only resolves as Ok when both are Ok\nResult\u003c(int, int), string\u003e resultZip = result1.Zip(result2);\n\n// Zip Results together\n// only resolves as Ok when both are Ok\nResult\u003cint, string\u003e resultSum = result1.Zip(result2, (a, b) =\u003e a + b);\n\n// Enumerate result, empty when error, singleton when error (see ToArray() also)\nIEnumerable\u003cint\u003e resultEnumerable = result1.AsEnumerable();\n\n// LINQ QUERY\n// you can use linq query to easily express map and bind\n\n// simple map\nvar result2Linq = from r in result1 select r + 1;\n\n// combining multiple results (fail fast at first non ok value)\nvar resultEvenSum =\n    from a in GetEvenNumber(2)\n    from b in GetEvenNumber(4)\n    from c in GetEvenNumber(6)\n    select a + b + c;\n}\n```\n\n### Async/Await\n\nThis library implements some helpers to seamless deal with async Result code\n\n```csharp\nvar result = GetEvenNumber(2);\n\n// async match overload\nint value1 = await result.Match(\n    async n =\u003e\n    {\n        await Task.Delay(n);\n        return n;\n    },\n    _ =\u003e -1\n);\n\nawait result.SwitchAsync(\n    async n =\u003e await Console.Out.WriteLineAsync($\"the number {n} is even\"),\n    async error =\u003e await Console.Error.WriteLineAsync(error)\n);\n\n// async projection counterparts\nResult\u003cint, string\u003e resultWithDelay = await result.SelectAsync(async n =\u003e\n{\n    await Task.Delay(n);\n    return n;\n});\n\n// Transform Result\u003cTask\u003cint\u003e, string\u003e in a awaitable Task\u003cResult\u003cint, string\u003e\u003e\nResult\u003cint, string\u003e resultWithDelay2 = await result.Select(async n =\u003e\n{\n    await Task.Delay(n);\n    return n;\n}).ToTask();\n```\n\n# Helper extensions\n\n```csharp\n// result collection\nvar results = new[] { GetEvenNumber(2), GetEvenNumber(3), GetEvenNumber(4) };\n\n// filter ok values\nIEnumerable\u003cint\u003e okResultsOnly = results.GetOkValues(); // [2,4]\n\n// map/reduce based on a result function\nvar numbers = new[] { 1, 2, 3, 4 };\nvar calculatedResults = numbers.ChooseResult(x =\u003e GetEvenNumber(x)); // [2,4]\n\n// group a collection of result into a Result of collection\n// collapse to error if any error is in the collection\nResult\u003cIReadOnlyList\u003cint\u003e, string\u003e singleResult = results.GroupResults();\n\n// Transform Result\u003cTask\u003cint\u003e, string\u003e in a awaitable Task\u003cResult\u003cint, string\u003e\u003e\nResult\u003cint, string\u003e resultWithDelay2 = await results[0].Select(async n =\u003e\n{\n    await Task.Delay(n);\n    return n;\n}).ToTask();\n```\n\n# FluentAssertions Extensions\n\n[NuGet package](https://www.nuget.org/packages/Resulteles.FluentAssertions) available:\n\n```ps\n$ dotnet add package Resulteles.FluentAssertions\n```\n\n# Alternatives\n\n- [FluentResults](https://github.com/altmann/FluentResults)\n- [language-ext](https://github.com/louthy/language-ext)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucasteles%2Fresulteles","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flucasteles%2Fresulteles","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucasteles%2Fresulteles/lists"}