コンテンツにスキップ

union(直和型)

union は、abstract record で宣言した基底と、その基底を継承する record の組です。

書き方説明注意
abstract record Shape; record Circle(float R) : Shape;宣言と値の生成
s switch { Circle c => ..., _ => ... }型による分岐
s switch { Circle c => ..., Rect r => ... }既定のケースを置かない分岐
A a => ..., B b => ..., C c => ...3 つ以上の型の分岐
s is Circle型の判定
void Use(Shape s)引数での受け取り
Shape Make()戻り値での返却
Shape[] all = new Shape[2];配列の要素
書き方説明エラー理由代替
private Shape held;フィールドに持つTUKI0001未実装種類の列挙型と中身を別々のフィールドに置く
abstract record Node; record Pair(Node L, Node R) : Node;自分自身を含む定義(再帰)TUKI0001環境配列と添字で木を表す
Debug.Log(s)union の値をそのまま外へ渡すTUKI0001環境先に型で分岐して、取り出した値を渡す
s switch { Line l when … => … }union の型パターンに条件を付けるTUKI0001未実装条件をケースの本体へ移すか、when を使わずケースを分ける

union の値は、ローカル変数・引数・戻り値・配列に置けます。フィールドには置けません。状態として残すときは、種類を表す列挙型の値と、それぞれの中身を、別々のフィールドに置きます。

値型(struct / record)に付けたインタフェースも同じ形で持たれ、どちらも、いま入っているのがどの型かを表す番号 1 つと、型ごとのヒープ変数を並べたものになります。Behaviour に付けたインタフェースだけは別の仕組みで、そちらは Behaviour そのものを指します。

数え方すべての型の中身を合計した数に、種類を表す番号のぶんを加えた数
重ね合わせしません。最も大きい型に合わせるのではありません
型を 1 つ増やすとその型の中身のぶんだけ増えます
上限Udon の実行モデル
using UnityEngine;
using Tsukimi;
public abstract record Shape;
public record Circle(float R) : Shape;
public record Rect(float W, float H) : Shape;
public class UnDeclare : TsukimiBehaviour
{
void Start()
{
Shape s = new Circle(1f);
float a = s switch
{
Circle c => c.R,
Rect r => r.W * r.H,
_ => 0f,
};
Debug.Log(a); // => 1
}
}
using UnityEngine;
using Tsukimi;
public abstract record Shape;
public record Circle(float R) : Shape;
public record Rect(float W, float H) : Shape;
public class UnSwitchWithDefault : TsukimiBehaviour
{
void Start()
{
Shape s = new Rect(2f, 3f);
float a = s switch
{
Circle c => c.R,
Rect r => r.W * r.H,
_ => 0f,
};
Debug.Log(a); // => 6
}
}

ケースを尽くしていれば、既定のケースは必要ありません。

using UnityEngine;
using Tsukimi;
public abstract record Shape;
public record Circle(float R) : Shape;
public record Rect(float W, float H) : Shape;
public class UnSwitchExhaustive : TsukimiBehaviour
{
void Start()
{
Shape s = new Circle(1f);
float a = s switch
{
Circle c => c.R,
Rect r => r.W * r.H,
};
Debug.Log(a); // => 1
}
}
using UnityEngine;
using Tsukimi;
public abstract record Shape;
public record A(int N) : Shape;
public record B(int N) : Shape;
public record C(int N) : Shape;
public class UnThreeCases : TsukimiBehaviour
{
void Start()
{
Shape s = new A(1);
int v = s switch { A a => a.N, B b => b.N, C c => c.N, _ => 0 };
Debug.Log(v); // => 1
}
}
using UnityEngine;
using Tsukimi;
public abstract record Shape;
public record Circle(float R) : Shape;
public record Rect(float W, float H) : Shape;
public class UnIsPattern : TsukimiBehaviour
{
void Start()
{
Shape s = new Circle(1f);
bool isCircle = s is Circle;
Debug.Log(isCircle); // => true
}
}
using UnityEngine;
using Tsukimi;
public abstract record Shape;
public record Circle(float R) : Shape;
public record Rect(float W, float H) : Shape;
public class UnParameter : TsukimiBehaviour
{
void Start()
{
Use(new Circle(1f));
}
private void Use(Shape s)
{
float a = s switch
{
Circle c => c.R,
Rect r => r.W * r.H,
_ => 0f,
};
Debug.Log(a); // => 1
}
}
using UnityEngine;
using Tsukimi;
public abstract record Shape;
public record Circle(float R) : Shape;
public record Rect(float W, float H) : Shape;
public class UnReturnValue : TsukimiBehaviour
{
void Start()
{
Shape s = Make();
float a = s switch
{
Circle c => c.R,
Rect r => r.W * r.H,
_ => 0f,
};
Debug.Log(a); // => 1
}
private Shape Make()
{
return new Circle(1f);
}
}
using UnityEngine;
using Tsukimi;
public abstract record Shape;
public record Circle(float R) : Shape;
public record Rect(float W, float H) : Shape;
public class UnArray : TsukimiBehaviour
{
void Start()
{
Shape[] all = new Shape[2];
all[0] = new Circle(1f);
all[1] = new Rect(1f, 2f);
float total = 0f;
for (int i = 0; i < all.Length; i++)
{
Shape s = all[i];
float a = s switch
{
Circle c => c.R,
Rect r => r.W * r.H,
_ => 0f,
};
total += a;
}
Debug.Log(total); // => 3
}
}