コンテンツにスキップ

union(直和型)

書き方説明
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未実装ローカル変数・引数・配列で受け渡す
record Pair(Node L, Node R) : Node;自分自身を含む定義(再帰)TUKI0001環境配列と添字で木を表す
Debug.Log(s)union の値をそのまま外へ渡すTUKI0001環境先に型で分岐して、取り出した値を渡す
union の値はフィールドに持てません。状態として残すときは、種類を表す列挙型の値と、それぞれの中身を、別々のフィールドに置きます。

値型(struct / record)に付けたインタフェースも、これと同じ形に変換されます。どちらも、いま入っているのがどの型かを表す番号 1 つと、型ごとの置き場を並べたものになります。書き方が違うだけで、動く仕組みは同じです。Behaviour に付けたインタフェースだけは別の仕組みで、そちらは Behaviour そのものを指します。

型ごとの置き場は別々で、重ねません。union が使うスロットの数は、すべての型の中身を足した数に、種類を表す番号のぶんを加えたものになります。いちばん大きい型に合わせるのではありません。型を 1 つ増やすと、その型の中身のぶんだけ増えます(スロットの上限はUdon の実行モデル)。

基底を abstract record で宣言し、それぞれの型を、その基底を継承する record で宣言します。

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
}
}