SharpUnion 1.0.0
See the version list below for details.
dotnet add package SharpUnion --version 1.0.0
NuGet\Install-Package SharpUnion -Version 1.0.0
<PackageReference Include="SharpUnion" Version="1.0.0" />
paket add SharpUnion --version 1.0.0
#r "nuget: SharpUnion, 1.0.0"
// Install SharpUnion as a Cake Addin #addin nuget:?package=SharpUnion&version=1.0.0 // Install SharpUnion as a Cake Tool #tool nuget:?package=SharpUnion&version=1.0.0
SharpUnion
Bringing the power of F# discriminated unions to C#.
Use
Write discriminated unions with nested records:
using SharpUnion.Shared;
namespace MyApp;
[SharpUnion]
public abstract partial record Shape
{
public partial record Circle(float Radius);
public partial record EquilateralTriangle(double SideLength);
public partial record Square(double SideLength);
public partial record Rectangle(double Height, double Width);
internal static double Area(Shape shape) =>
shape switch
{
// alt pattern matching syntax: Circle { Radius: var radius } => Math.PI * radius * radius,
Circle(var radius) => Math.PI * radius * radius,
EquilateralTriangle(var side) => Math.Sqrt(3.0) / 4.0 * side * side,
Square(var side) => side * side,
Rectangle(var height, var width) => height * width,
_ => throw new NotImplementedException(),
};
}
[SharpUnion]
internal abstract partial record Result<T>
{
internal partial record OK(T Value);
internal partial record Error(string Message);
}
The generator will generate code that looks like the following:
namespace MyApp
{
abstract partial record Shape
{
private Shape() {}
internal sealed partial record Circle : Shape;
internal bool IsCircle => this is Circle;
internal sealed partial record EquilateralTriangle : Shape;
internal bool IsEquilateralTriangle => this is EquilateralTriangle;
internal sealed partial record Square : Shape;
internal bool IsSquare => this is Square;
internal sealed partial record Rectangle : Shape;
internal bool IsRectangle => this is Rectangle;
}
}
namespace MyApp
{
abstract partial record Result<T>
{
private Result() {}
internal sealed partial record OK : Result<T>;
internal bool IsOK => this is OK;
internal sealed partial record Error : Result<T>;
internal bool IsError => this is Error;
}
}
Logic:
- Force a private constructor on the parent type so nobody can create a new instance of it.
- Mark each implementation as
sealed
, so nobody can derive from them. - Implement
Is*
properties. Favor pattern matching when using, though.
Serialization
Set the Serializable
property on your attribute: [SharpUnion(Serializable = true)]
. This will add support for System.Text.Json serialization. When this flag is set, the following code will work:
var type = new Shape.Circle(5f);
var json = JsonSerializer.Serialize(type);
var resultCircle = JsonSerializer.Deserialize<Shape.Circle>(json);
var resultShape = JsonSerializer.Deserialize<Shape>(json);
Analyzers
Some analyzers are included to help prevent issues.
Child Member with Generic
Generics must be included on the parent type; defining generic child types is not allowed (child members may use generics included on the parent type, however). This analyzer will raise an error.
Invalid Accessibility
DUs must be internal or public. Private types don't make sense in this case, because the derived members will not be visible, and protected types don't make sense because DUs cannot be further derived. This analyzer will raise an error.
Mismatched Accessibility
DUs and their members must have the same accessibility modifier. This analyzer will raise an error.
Serialization flag on Generic DU
Generic DUs (such as the Result<T>
shown above), cannot be deserialized.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- PolySharp (>= 1.14.1)
- SharpUnion.Shared (>= 1.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.