RustlikeValues.Option
1.0.0
There is a newer version of this package available.
See the version list below for details.
See the version list below for details.
dotnet add package RustlikeValues.Option --version 1.0.0
NuGet\Install-Package RustlikeValues.Option -Version 1.0.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="RustlikeValues.Option" Version="1.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RustlikeValues.Option" Version="1.0.0" />
<PackageReference Include="RustlikeValues.Option" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add RustlikeValues.Option --version 1.0.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: RustlikeValues.Option, 1.0.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package RustlikeValues.Option@1.0.0
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=RustlikeValues.Option&version=1.0.0
#tool nuget:?package=RustlikeValues.Option&version=1.0.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
RustlikeValues.Option
A Rust-inspired Option<T>
type for C# that provides safe nullable value handling and eliminates null reference exceptions.
📦 Installation
dotnet add package RustlikeValues.Option
🎯 What is Option<T>?
The Option<T>
type represents an optional value: every Option
is either:
- Some - contains a value of type
T
- None - contains no value
This eliminates null reference exceptions and makes nullable handling explicit and safe.
🚀 Quick Start
using RustlikeValues.RustlikeOption;
// Creating Options
var some = Option.Some(42);
var none = Option.None<int>();
// Safe transformations
var result = some
.Map(x => x * 2) // Transform the value if present
.Filter(x => x > 50) // Keep only if condition is true
.UnwrapOr(0); // Get value or default
// result = 84
📚 Core API
Creation
// Create Some variant
var some = Option.Some("Hello");
var someInt = Option.Some(42);
// Create None variant
var none = Option.None<string>();
// Safe creation from potentially throwing code
var option = Option.TryCreate(() => int.Parse("123"));
Checking State
var option = Option.Some(42);
if (option.IsSome)
{
Console.WriteLine("Has value!");
}
if (option.IsNone)
{
Console.WriteLine("No value");
}
// Implicit conversion to bool
if (option) // true if Some, false if None
{
Console.WriteLine("Has value!");
}
Getting Values
var option = Option.Some(42);
// Get value or throw exception
var value = option.Unwrap(); // 42
// Get value or use default
var value = option.UnwrapOr(0); // 42
// Get value or compute from function
var value = option.UnwrapOrElse(() => DateTime.Now.Millisecond);
// Get value or null/default(T) - may return null!
var value = option.GetValueOrDefault(); // 42 or null/default
// Safe alternative to Unwrap (returns the option itself)
var safeOption = option.TryUnwrap(); // returns the option, never throws
Transformations
var option = Option.Some("hello");
// Map: transform the value if present
var upper = option.Map(s => s.ToUpper()); // Some("HELLO")
// Filter: keep value only if predicate is true
var filtered = option.Filter(s => s.Length > 3); // Some("hello")
// AndThen: chain operations that return Options
var result = option.AndThen(s =>
s.Length > 0 ? Option.Some(s.Length) : Option.None<int>());
Async Operations
var option = Option.Some("https://api.example.com");
// Async map
var response = await option.MapAsync(async url =>
await httpClient.GetStringAsync(url));
// Async AndThen
var parsed = await option.AndThenAsync(async url =>
{
var json = await httpClient.GetStringAsync(url);
return TryParseJson(json);
});
Combining Options
var name = Option.Some("John");
var age = Option.Some(30);
// Zip two options together
var person = name.Zip(age); // Some(("John", 30))
// Use one option or another
var option1 = Option.None<string>();
var option2 = Option.Some("fallback");
var result = option1.Or(option2); // Some("fallback")
// Compute alternative if None
var result = option1.OrElse(() => Option.Some("computed"));
🎭 Pattern Matching
var option = Option.Some(42);
// Match with return value
var result = option.Match(
Some: value => $"Got {value}",
None: () => "No value"
);
// Match with side effects
option.Match(
Some: value => Console.WriteLine($"Value: {value}"),
None: () => Console.WriteLine("No value")
);
// Deconstruction
var (isSome, value) = option;
if (isSome)
{
Console.WriteLine($"Value: {value}");
}
🔧 LINQ Integration
using RustlikeValues.RustlikeOption;
// Option implements IEnumerable<T>
var numbers = new[]
{
Option.Some(1),
Option.None<int>(),
Option.Some(3)
};
var sum = numbers
.SelectMany(opt => opt) // Flatten Some values
.Sum(); // 4
// Use with LINQ Where, Select, etc.
var result = Option.Some(42)
.Where(x => x > 0)
.Select(x => x * 2); // Some(84)
📄 JSON Serialization
Options serialize naturally with System.Text.Json:
public class User
{
public string Name { get; set; }
public Option<string> Email { get; set; }
public Option<int> Age { get; set; }
}
var user = new User
{
Name = "John",
Email = Option.Some("john@example.com"),
Age = Option.None<int>()
};
var json = JsonSerializer.Serialize(user);
// {"Name":"John","Email":"john@example.com","Age":null}
var deserialized = JsonSerializer.Deserialize<User>(json);
// Email = Some("john@example.com"), Age = None
🔄 Implicit Conversions
// Implicit conversion from T to Option<T>
Option<string> option = "hello"; // Some("hello")
// Implicit conversion to bool
if (option) // true if Some
{
Console.WriteLine("Has value");
}
🏃♂️ Performance
- Zero allocation for None values (static readonly)
- Minimal overhead for Some values (single allocation)
- Aggressive inlining for hot path methods
- Struct-based design for stack allocation
📖 Examples
Safe Dictionary Access
var dict = new Dictionary<string, int> { ["key"] = 42 };
// Old way - prone to exceptions
// var value = dict["key"]; // KeyNotFoundException if missing
// New way - safe
var option = dict.ContainsKey("key")
? Option.Some(dict["key"])
: Option.None<int>();
var result = option.UnwrapOr(0);
Safe Parsing
// Safe integer parsing
var input = "123";
var number = Option.TryCreate(() => int.Parse(input))
.Filter(x => x > 0)
.Map(x => x * 2)
.UnwrapOr(0);
Chaining Operations
public Option<User> GetUser(int id) => /* ... */;
public Option<Profile> GetProfile(User user) => /* ... */;
public Option<string> GetAvatarUrl(Profile profile) => /* ... */;
// Chain operations safely
var avatarUrl = GetUser(userId)
.AndThen(GetProfile)
.AndThen(GetAvatarUrl)
.UnwrapOr("/default-avatar.png");
🔗 Related Packages
- RustlikeValues.Result - For error handling with Result<T, E>
- RustlikeValues.Extensions - Additional utility methods
- RustlikeValues - Meta-package containing all types
🤝 Contributing
Contributions are welcome! Please feel free to submit issues, feature requests, or pull requests.
📄 License
This project is licensed under the MIT License.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. 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. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net9.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.