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]; | 配列の要素 |
非対応(4)
Section titled “非対応(4)”| 書き方 | 説明 | エラー | 理由 | 代替 |
|---|---|---|---|---|
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 の値は、ローカル変数・引数・戻り値・配列に置けます。フィールドには置けません。状態として残すときは、種類を表す列挙型の値と、それぞれの中身を、別々のフィールドに置きます。
インタフェースとの関係
Section titled “インタフェースとの関係”値型(struct / record)に付けたインタフェースも同じ形で持たれ、どちらも、いま入っているのがどの型かを表す番号 1 つと、型ごとのヒープ変数を並べたものになります。Behaviour に付けたインタフェースだけは別の仕組みで、そちらは Behaviour そのものを指します。
使うヒープ変数の数
Section titled “使うヒープ変数の数”| 数え方 | すべての型の中身を合計した数に、種類を表す番号のぶんを加えた数 |
| 重ね合わせ | しません。最も大きい型に合わせるのではありません |
| 型を 1 つ増やすと | その型の中身のぶんだけ増えます |
| 上限 | Udon の実行モデル |
宣言と値の生成
Section titled “宣言と値の生成”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 }}型による分岐
Section titled “型による分岐”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 }}既定のケースを置かない分岐
Section titled “既定のケースを置かない分岐”ケースを尽くしていれば、既定のケースは必要ありません。
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 }}3 つ以上の型の分岐
Section titled “3 つ以上の型の分岐”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 }}引数での受け取り
Section titled “引数での受け取り”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 }}戻り値での返却
Section titled “戻り値での返却”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 }}