FlowOnRails 0.1.0
dotnet add package FlowOnRails --version 0.1.0
NuGet\Install-Package FlowOnRails -Version 0.1.0
<PackageReference Include="FlowOnRails" Version="0.1.0" />
<PackageVersion Include="FlowOnRails" Version="0.1.0" />
<PackageReference Include="FlowOnRails" />
paket add FlowOnRails --version 0.1.0
#r "nuget: FlowOnRails, 0.1.0"
#:package FlowOnRails@0.1.0
#addin nuget:?package=FlowOnRails&version=0.1.0
#tool nuget:?package=FlowOnRails&version=0.1.0
FlowOnRails
This is my first public library. I originally created it to solve my own difficulties with error handling in C# and decided to share it. I am new to creating open source packages and still learning without strict guidance. Any feedback or contribution is welcome.
FlowOnRails is a library built to bring Railway Oriented Programming to C# natively and with a focus on developer experience.
Features
- Zero Allocations. Built with readonly partial structs. Returning successful results does not allocate memory on the heap.
- Strong Typing. It avoids using strings or hidden exceptions for errors. You create your own error records inheriting from a base Error class.
- LINQ Support. You can write complex flows using native C# query syntax.
- Async Integration. Built-in extensions for Task and ValueTask.
- Flow Transitions. Fluid methods like Bind, Map, and MapError allow you to seamlessly transition between void operations and operations that return values.
Installation
dotnet add package FlowOnRails --prerelease
Usage
Defining Errors
You can create errors using records:
public record ValidationError(string Message) : Error;
public record NotFoundError(string Message) : Error;
Returning a Rail
The library uses Rail for flows that do not return data and RailFor for flows with data.
public RailFor<User> GetUser(int id)
{
if (id <= 0)
return Rail.Fail(new ValidationError("ID must be positive."));
var user = Database.Find(id);
if (user is null)
return Rail.Fail(new NotFoundError("User not found."));
return RailFor<User>.Ok(user);
}
Using LINQ
You can use LINQ to chain logic. If any step fails, the flow is interrupted and the error is returned immediately:
public RailFor<Receipt> ProcessCheckout(int userId, Cart cart)
{
var result =
from user in GetUser(userId)
from stock in CheckStock(cart)
from payment in ProcessPayment(user, cart)
select GenerateReceipt(payment);
return result;
}
Unwrapping
When you need to extract the final result, you can use the TryUnwrap method:
var rail = GetUser(10);
if (!rail.TryUnwrap(out var user, out var error))
{
Console.WriteLine($"Failed: {error.Message}");
return;
}
Console.WriteLine($"Success: {user.Name}");
Async Extensions
FlowOnRails provides extensions like BindAsync, MapAsync and MapErrorAsync for asynchronous operations:
var result = await GetUserAsync(id)
.MapErrorAsync(e => new DomainError($"Failed to fetch user: {e.Message}"))
.BindAsync(user => ProcessUserAsync(user));
Contributing
Feel free to open an Issue or submit a Pull Request if you find a bug or want to propose improvements.
License
Distributed under the MIT License. See the LICENSE file for more details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0 | 93 | 9/13/2026 |