Use OneOf as a method parameter
masterUse OneOf as a parameter type to allow a method to accept different types without requiring multiple overloads.
public void SetBackground(OneOf<string, ColorName, Color> backgroundColor) { ... }repository·master·Indexed 26 days ago
https://github.com/mcintyre321/oneofOneOf provides F#-style discriminated unions for C#, allowing developers to represent a value that can be one of several types. It enables exhaustive pattern matching via Match() and Switch(), safer error handling without exceptions, and the creation of reusable types using OneOfBase and the OneOf.SourceGenerator.
Use OneOf as a parameter type to allow a method to accept different types without requiring multiple overloads.
public void SetBackground(OneOf<string, ColorName, Color> backgroundColor) { ... }Option pattern by declaring OneOf<Something, None>. The OneOf.Types namespace provides several useful types for this purpose, including Yes, No, Maybe, Unknown, True, False, All, Some, and None.To use OneOf in your C# project, install the NuGet package:
install-package OneOfOneOf is frequently used as a return type to represent multiple possible outcomes (e.g., a success value or specific error types) without using exceptions for control flow. This provides a strongly typed method signature that forces the consumer to handle all possible cases.
public OneOf<User, InvalidName, NameTaken> CreateUser(string username)
{
if (!IsValid(username)) return new InvalidName();
var user = _repo.FindByUsername(username);
if(user != null) return new NameTaken();
var user = new User(username);
_repo.Save(user);
return user;
}You can automate the boilerplate for OneOfBase using the OneOf.SourceGenerator package. Apply the [GenerateOneOf] attribute to a partial class that inherits from OneOfBase.
Install-Package OneOf.SourceGenerator[GenerateOneOf]
public partial class StringOrNumber : OneOfBase<string, int> { }The .TryPickX methods (where X is the index of the generic type, e.g., TryPickT0, TryPickT1) allow you to attempt to extract a specific type. If the OneOf contains that type, the method returns true, sets the out value, and provides the remainder (a OneOf containing all other types).
// For OneOf<Thing, NotFound, Error>
if (thingOrNotFoundOrError.TryPickT1(out NotFound notFound, out var thingOrError))
return StatusCode(404);The Match method allows you to extract the value from a OneOf instance by providing a handler function for every generic type argument. The number of handlers must match the number of generic arguments. This ensures exhaustive handling of all possible types.
OneOf<string, ColorName, Color> backgroundColor = ...;
Color c = backgroundColor.Match(
str => CssHelper.GetColorFromString(str),
name => new Color(name),
col => col
);Inherit from OneOfBase<T0, ... Tn> to create a named, reusable type. This allows you to add custom members and define implicit conversions to make the type easier to work with.
public class StringOrNumber : OneOfBase<string, int>
{
StringOrNumber(OneOf<string, int> _) : base(_) { }
public static implicit operator StringOrNumber(string _) => new StringOrNumber(_);
public static implicit operator StringOrNumber(int _) => new StringOrNumber(_);
public (bool isNumber, int number) TryGetNumber() =>
Match(
s => (int.TryParse(s, out var n), n),
i => (true, i)
);
}Use the .Switch method when you want to perform an action for each possible type without returning a value.
OneOf<string, DateTime> dateValue = ...;
dateValue.Switch(
str => AddEntry(DateTime.Parse(str), foo),
int => AddEntry(int, foo)
);