Last active
June 10, 2026 11:12
-
-
Save aetos382/426e249fa269d2d30656eb2fec3948f4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Diagnostics; | |
| using System.Diagnostics.CodeAnalysis; | |
| using System.Runtime.CompilerServices; | |
| TestStandardUnion(); | |
| TestCustomUnion1(); | |
| TestCustomUnion2(); | |
| TestCustomUnion3(); | |
| void TestStandardUnion() | |
| { | |
| StandardUnion u = 1; | |
| var underlyingType = u switch | |
| { | |
| int => "int", | |
| string => "string", | |
| _ => "unknown" | |
| }; | |
| Console.WriteLine($"union is {underlyingType}."); | |
| } | |
| void TestCustomUnion1() | |
| { | |
| CustomUnion1 u = 1; | |
| var underlyingType = u switch | |
| { | |
| int => "int", | |
| string => "string", | |
| _ => "unknown" | |
| }; | |
| Console.WriteLine($"union is {underlyingType}."); | |
| } | |
| void TestCustomUnion2() | |
| { | |
| CustomUnion2 u = 1; | |
| var underlyingType = u switch | |
| { | |
| int => "int", | |
| string => "string", | |
| _ => "unknown" | |
| }; | |
| Console.WriteLine($"union is {underlyingType}."); | |
| } | |
| void TestCustomUnion3() | |
| { | |
| CustomUnion3 u = 1; | |
| var underlyingType = u switch | |
| { | |
| int => "int", | |
| string => "string", | |
| _ => "unknown" | |
| }; | |
| Console.WriteLine($"union is {underlyingType}."); | |
| } | |
| // boxing する | |
| union StandardUnion(int, string); | |
| // boxing する | |
| // public な 1 引数コンストラクタは union constructor になる | |
| [Union] | |
| readonly struct CustomUnion1 : IUnion | |
| { | |
| public CustomUnion1(int value) => Value = value; | |
| public CustomUnion1(string value) => Value = value; | |
| public object? Value { get; } | |
| } | |
| // boxing しない | |
| // public な 1 引数コンストラクタは union constructor になる | |
| [Union] | |
| readonly struct CustomUnion2 : IUnion | |
| { | |
| private enum ValueKind | |
| { | |
| None, | |
| Int, | |
| String | |
| } | |
| private readonly ValueKind _kind; | |
| private readonly int _intValue; | |
| private readonly string? _stringValue; | |
| public CustomUnion2(int value) | |
| { | |
| _kind = ValueKind.Int; | |
| _intValue = value; | |
| } | |
| public CustomUnion2(string value) | |
| { | |
| _kind = ValueKind.String; | |
| _stringValue = value; | |
| } | |
| public bool TryGetValue(out int value) | |
| { | |
| if (_kind != ValueKind.Int) | |
| { | |
| value = 0; | |
| return false; | |
| } | |
| value = _intValue; | |
| return true; | |
| } | |
| public bool TryGetValue([MaybeNullWhen(false)] out string value) | |
| { | |
| if (_kind != ValueKind.String) | |
| { | |
| value = null; | |
| return false; | |
| } | |
| value = _stringValue!; | |
| return true; | |
| } | |
| public object? Value => | |
| _kind switch | |
| { | |
| ValueKind.None => null, | |
| ValueKind.Int => _intValue, | |
| ValueKind.String => _stringValue, | |
| _ => throw new UnreachableException() | |
| }; | |
| } | |
| // boxing しない | |
| // IUnionMembers.Create に定義された型変換のみが union constructor になる | |
| [Union] | |
| readonly struct CustomUnion3 : IUnion, CustomUnion3.IUnionMembers | |
| { | |
| public interface IUnionMembers | |
| { | |
| static abstract CustomUnion3 Create(int value); | |
| static abstract CustomUnion3 Create(string value); | |
| bool TryGetValue(out int value); | |
| bool TryGetValue([MaybeNullWhen(false)] out string value); | |
| object? Value { get; } | |
| } | |
| private enum ValueKind | |
| { | |
| None, | |
| Int, | |
| String | |
| } | |
| private readonly ValueKind _kind; | |
| private readonly int _intValue; | |
| private readonly string? _stringValue; | |
| public static CustomUnion3 Create(int value) => new(value); | |
| public static CustomUnion3 Create(string value) => new(value); | |
| // これは union constructor ではない | |
| // CustomUnion3 u = new CustomUnion3(1.0); として呼び出すことは可能 | |
| // CustomUnion3 u = 1.0; は不可能 | |
| public CustomUnion3(double value) | |
| { | |
| } | |
| private CustomUnion3(int value) | |
| { | |
| _kind = ValueKind.Int; | |
| _intValue = value; | |
| } | |
| private CustomUnion3(string value) | |
| { | |
| _kind = ValueKind.String; | |
| _stringValue = value; | |
| } | |
| public bool TryGetValue(out int value) | |
| { | |
| if (_kind != ValueKind.Int) | |
| { | |
| value = 0; | |
| return false; | |
| } | |
| value = _intValue; | |
| return true; | |
| } | |
| public bool TryGetValue([MaybeNullWhen(false)] out string value) | |
| { | |
| if (_kind != ValueKind.String) | |
| { | |
| value = null; | |
| return false; | |
| } | |
| value = _stringValue!; | |
| return true; | |
| } | |
| public object? Value => _kind switch | |
| { | |
| ValueKind.None => null, | |
| ValueKind.Int => _intValue, | |
| ValueKind.String => _stringValue, | |
| _ => throw new UnreachableException() | |
| }; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment