Dunet 1.4.1-preview2

This is a prerelease version of Dunet.
There is a newer version of this package available.
See the version list below for details.
dotnet add package Dunet --version 1.4.1-preview2
                    
NuGet\Install-Package Dunet -Version 1.4.1-preview2
                    
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="Dunet" Version="1.4.1-preview2">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Dunet" Version="1.4.1-preview2" />
                    
Directory.Packages.props
<PackageReference Include="Dunet">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
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 Dunet --version 1.4.1-preview2
                    
#r "nuget: Dunet, 1.4.1-preview2"
                    
#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 Dunet@1.4.1-preview2
                    
#: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=Dunet&version=1.4.1-preview2&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Dunet&version=1.4.1-preview2&prerelease
                    
Install as a Cake Tool

Dunet

Dunet is a simple source generator for discriminated unions in C#.

Install

  • NuGet: dotnet add package dunet

Usage

// 1. Import the namespace.
using Dunet;

// 2. Add the `Union` attribute to a partial record.
[Union]
partial record Shape
{
    // 3. Define the union members as inner partial records.
    partial record Circle(double Radius);
    partial record Rectangle(double Length, double Width);
    partial record Triangle(double Base, double Height);
}

// 4. Use the union members.
var shape = new Shape.Rectangle(3, 4);
var area = shape.Match(
    circle => 3.14 * circle.Radius * circle.Radius,
    rectangle => rectangle.Length * rectangle.Width,
    triangle => triangle.Base * triangle.Height / 2
);
Console.WriteLine(area); // "12"

Generics Support

Use generics for more advanced union types. For example, an option monad:

// 1. Import the namespace.
using Dunet;
// Optional: use aliasing for more terse code.
using static Option<int>;

// 2. Add the `Union` attribute to a partial record.
// 3. Add one or more type arguments to the union record.
[Union]
partial record Option<T>
{
    partial record Some(T Value);
    partial record None();
}

// 4. Use the union members.
Option<int> ParseInt(string? value) =>
    int.TryParse(value, out var number)
        ? new Some(number)
        : new None();

string GetOutput(Option<int> number) =>
    number.Match(
        some => some.Value.ToString(),
        none => "Invalid input!"
    );

var input = Console.ReadLine(); // User inputs "not a number".
var result = ParseInt(input);
var output = GetOutput(result);
Console.WriteLine(output); // "Invalid input!"

input = Console.ReadLine(); // User inputs "12345".
result = ParseInt(input);
output = GetOutput(result);
Console.WriteLine(output); // "12345".

Implicit Conversion Support

Given a union type where all members contain only a single parameter and all parameters are a different type, Dunet will generate implicit conversions between their values and the union type.

For example, consider a Result union type that represents success as a double and failure as an Exception:

// 1. Import the namespace.
using Dunet;

// 2. Define a union type with single unique member values:
[Union]
partial record Result
{
    partial record Success(double Value);
    partial record Failure(Exception Error);
}

// 3. Return union member values directly.
Result Divide(double numerator, double denominator)
{
    if (denominator is 0d)
    {
        // No need for `new Result.Failure(new InvalidOperationException("..."));`
        return new InvalidOperationException("Cannot divide by zero!");
    }

    // No need for `new Result.Success(...);`
    return numerator / denominator;
}

var result = Divide(42, 0);
var output = result.Match(
    success => success.Value.ToString(),
    failure => failure.Error.Message
);

Console.WriteLine(output); // "Cannot divide by zero!"

Async Match Support

Dunet generates a MatchAsync() extension method for all Task<T> and ValueTask<T> where T is a union type. For example:

// Choice.cs

using Dunet;

namespace Core;

// 1. Define a union type within a namespace.
[Union]
partial record Choice
{
    partial record Yes;
    partial record No(string Reason);
}
// Program.cs

using Core;
using static Core.Choice;

// 2. Define async methods like you would for any other type.
static async Task<Choice> AskAsync()
{
    // Simulating network call.
    await Task.Delay(1000);

    // 3. Return unions from async methods like any other type.
    return new No("because I don't wanna!");
}

// 4. Asynchronously match any union `Task` or `ValueTask`.
var response = await AskAsync().MatchAsync(yes => "Yes!!!", no => $"No, {no.Reason}");

Console.WriteLine(response); // Prints "No, because I don't wanna!" after 1 second.

Note: MatchAsync() can only be generated for namespaced unions.

Nested Union Support

To declare a union nested within a class or record, the class or record must be partial. For example:

// This type declaration must be partial.
public partial class Parent1
{
    // So must this one.
    public partial class Parent2
    {
        // Unions must always be partial.
        [Union]
        public partial record Nested
        {
            public partial record Member1;
            public partial record Member2;
        }
    }
}

// Access union members like any other nested type.
var member1 = new Parent1.Parent2.Nested.Member1();

Samples

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

NuGet packages (10)

Showing the top 5 NuGet packages that depend on Dunet:

Package Downloads
ZeroC.Slice

Slice for C#.

InsurScan.Models

API contracts for InsurScan platform. Contains request/response models for building custom clients or integrating with the InsurScan API.

Xenial.Identity.Client

Package Description

TeaPie

The core of TeaPie.Tool in form of library.

Morphir

Morphir executable package for AOT and single-file deployments

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.16.2 675 4/25/2026
1.16.1 22,834 2/16/2026
1.16.0 241 2/14/2026
1.15.0 5,967 1/29/2026
1.14.0 23,426 1/27/2026
1.13.1 1,091 1/25/2026
1.13.0 293 1/25/2026
1.13.0-preview2 103 1/25/2026
1.13.0-preview1 104 1/25/2026
1.12.0 2,112 1/19/2026
1.12.0-preview1 109 1/19/2026
1.11.4 1,484 1/17/2026
1.11.4-preview3 108 1/17/2026
1.11.4-preview2 119 1/17/2026 1.11.4-preview2 is deprecated because it is no longer maintained and has critical bugs.
1.11.4-preview1 117 1/17/2026 1.11.4-preview1 is deprecated because it is no longer maintained and has critical bugs.
1.11.3 94,126 6/13/2025
1.11.2 230,071 1/29/2024
1.11.1 563 1/27/2024
1.11.0 9,015 1/4/2024
1.4.1-preview2 1,611 11/5/2022 1.4.1-preview2 is deprecated because it is no longer maintained and has critical bugs.
Loading failed

1.4.1-preview2 - Disable CS1591 in generated extensions.
1.4.1-preview1 - Disable CS1591 in generated code.
1.4.0 - Support Action match functions.
1.3.0 - Async match methods.
1.2.0 - Support nested union declarations.
1.1.0 - Add implicit conversions for union members.
1.0.2 - Support multiple unions with the same name.
1.0.1 - Configure Dunet as development dependency.
1.0.0 - Production release.
0.5.0 - Generate dedicated match method on union records.
0.4.0 - Add support for declaring a union with records.
0.3.0 - Support complex types in union members.
0.2.2 - Add source generator DLL to package.
0.2.1 - Update readme.
0.2.0 - Generate dedicated match method.
0.1.3 - Add support for declaring unions inside top level programs.
0.1.2 - Simplify generated source.
0.1.1 - Support any number of interfaces.
0.1.0 - Initial release.