Dersei.Zorya
1.1.0
dotnet add package Dersei.Zorya --version 1.1.0
NuGet\Install-Package Dersei.Zorya -Version 1.1.0
<PackageReference Include="Dersei.Zorya" Version="1.1.0" />
paket add Dersei.Zorya --version 1.1.0
#r "nuget: Dersei.Zorya, 1.1.0"
// Install Dersei.Zorya as a Cake Addin #addin nuget:?package=Dersei.Zorya&version=1.1.0 // Install Dersei.Zorya as a Cake Tool #tool nuget:?package=Dersei.Zorya&version=1.1.0
Zorya
C# implementation of the variant type.
Implementation of the variant type both as a class (Variant
) and a structure (ValueVariant
). Both types support up to eight elements and implement implicit cast operators.
Using a variant
ValueVariant<int> v = 42;
ValueVariant<int, string> v = "42";
ValueVariant<int, string, double> v = 42.0;
or
Variant<int> v = 42;
Variant<int, string> v = "42";
Variant<int, string, double> v = 10.0;
It's also possible to use a constructor:
ValueVariant<int, double, string> v = new (42);
Getting a value
Getting a value is possible with Get
method which throws BadVariantAccessException
or BadValueVariantAccessException
if there's no element of the requested type:
Variant<int, string, double> v = 42.0;
v.Get<double>();
or with TryGet
which returns true
if the element exists or false
if it doesn't:
ValueVariant<int, string, double, long> v = 42L;
if (v.TryGet(out long value))
{
return value * 2;
}
Using a value
Additionally, there are also Match
, TryMatch
and MatchOrDefault
methods receiving Action
or Func
.
They apply the given function on the element of requested type. Match
throws BadVariantAccessException
or BadValueVariantAccessException
, TryMatch
returns true
if the element exists or false
if it doesn't.
MatchOrDefault
executes given fallback action in case of MatchOrDefault(Action)
or returns given default value in case of MatchOrDefault(Func)
.
Variant<int, string, double> v = 42.0;
v.Match((int i) => Console.WriteLine($"int {i}"));
Variant<int, string> v2 = "42";
v2.MatchOrDefault((int i) => Console.WriteLine($"int {i}"), () => Console.WriteLine("Incorrect type"));
Variant<int, double> v3 = 42.0;
if(v3.TryMatch((int i) => i * 10, out var result))
{
Console.WriteLine(result);
}
Visit
Visit
method accepts one function for all types the variant may contain, and then executes the one corresponding to the set type.
Variant<int, double, string> v = 42.0;
v.Visit((int i) => Console.WriteLine($"int {i}"), (double d) => Console.WriteLine($"double {d}", (string s) => Console.WriteLine($"string {s}");
Additional capabilities
It's also possible to request the set type using GetSetType
:
Variant<int, string, double, Point> v = new Point(0, 1);
if(v.GetSetType() == typeof(Point))
{
}
Because ValueVariant
can be initialized without setting any value, it's possible to test if anything is set using IsValid
method.
var v = new ValueVariant<int, string>();
Debug.Assert(v.IsValid()); //false
IsValid
will also return false
in the following cases:
ValueVariant<int, string>() v1 = default;
Debug.Assert(v1.IsValid()); //false
ValueVariant<int, string>() v2 = new ValueVariant<int, string>(null);
Debug.Assert(v2.IsValid()); //false
Variant<int, string>() v3 = null;
Debug.Assert(v3.IsValid()); //false (extension method)
Variant<int, string>() v4 = new Variant<int, string>(null);
Debug.Assert(v4.IsValid()); //false (extension method)
Method IsSet
allows testing if a specified type is set in the variant.
ValueVariant<int, string>() v = 10;
Debug.Assert(v.IsSet<int>()); //true
Debug.Assert(v.IsSet<string>()); //false
Variant
also allows setting a new element without creating a new object using Set
method which returns true
if successful:
Variant<int, string> v = new (10);
var wasSetSuccess = v.Set("20");
Debug.Assert(v.Get<string>() == "20"); //true
Debug.Assert(wasSetSuccess); //true
Get
, TryGet
, Match
, TryMarch
, MatchOrDefault
methods are also defined as static on individual types and Variant
, and ValueVariant
classes:
Variant<int, string, double, long> v = 42L;
var l = Variant.Get<long>(v);
or
Variant<int, string, double, long> v = 42L;
var l = Variant<int, string, double, long>.Get<long>(v);
Example of use case
Variant<int, double, string> ParseInput(string input)
{
if (int.TryParse(input, out var i))
{
return i;
}
if (double.TryParse(input, out var d))
{
return d;
}
return input;
}
Remarks
Types
Both types allow support only explicitly set types. Although it's possible to set a variant to hold an object of a child class of one of its types, there's no possibility to extract that object in the other way than by using a parent type. For example:
Variant<Parent> v = new Child();
v.Get<Child>(); //throws BadVariantAccessException
v.Get<Parent>(); //returns the Child object
The same is true for other methods like TryGet
or Visit
.
IsValid()
Both Variant
and ValueVariant
can be in invalid state. There are three possible reasons for that:
- creating either of the types with the constructor passing in
null
when it's possible. - setting
Variant
object tonull
. - initialising
ValueVariant
with an empty constructor ordefault
.
Method IsValid
allows checking if the variant is valid. For Variant
this method is implemented as an extension method allowing null
check.
Although it's still possible in some cases to pass null
to constructor, the variant behaviour in such cases will be undefined.
Until the version 1.0.1, due to the way value types and implicit operators work, it was possible to create a ValueVariant
(with one reference type or object
and another reference type) using null
.
For example: ValueVariant<string, int> v = null;
or ValueVariant<string, object, int> v = null;
Since the version 1.0.2 such operation will result in a default ValueVariant
without any value set and with IsValid
method returning false
.
Equality
Until the version 1.0.1 variants used default equality. Since the version 1.0.2 all variants support IEquatable
interface, ==
, !=
operators and Equals
method.
In case of the Variant
type two objects v1
and v2
are equal if:
- they have the same type, including the order of types,
v1 is not null && v2 is not null
,ReferenceEquals(v1, v2)
returns true,- otherwise, if they both have the same items set and values of those items are the same.
In case of the ValueVariant
type two objects v1
and v2
are equal if:
- they have the same type, including the order of types,
- they both have the same items set and values of those items are the same.
Name
Zorya (lit. "Dawn"; also many variants: Zarya, Zara, Zaranitsa, Zoryushka, etc.) is a figure in Slavic folklore, a feminine personification of dawn, possibly goddess. Depending on tradition, she may appear as a singular entity, often called "The Red Maiden", or two or three sisters at once. Zorya - Wikipedia.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. 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. |
-
net6.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.