メンバの宣言
対応(42)
Section titled “対応(42)”| 書き方 | 説明 | 注意 |
|---|---|---|
private int count; | フィールド | |
private int count = 5; | 宣言と同時の代入 | |
private const int Max = 10; | 定数 | |
private static int Count; | 静的フィールド | 値は Behaviour のインスタンスごとに別で、インスタンスのあいだで共有されません。 |
private static readonly int Max = 10; | 静的な読み取り専用フィールド | |
private void Do() | メソッドの宣言 | |
private int Get() | 戻り値のあるメソッド | |
private int Add(int a, int b) | 引数のあるメソッド | |
int Add(int a, int b = 2) | 既定の引数 | |
Add(b: 2, a: 1) | 名前つき引数 | |
Add(int, int) / Add(float, float) | オーバーロード | |
private int Twice(int n) => n * 2; | 式形式のメソッド | |
private static int Zero() | 静的メソッド | |
public int Value { get; set; } | 自動プロパティ | |
public int Doubled { get { return n * 2; } } | 計算するプロパティ | struct の中では set を書けません(struct と record)。 |
{ get; private set; } | 取得と設定で異なる可視性 | |
{ get; set; } = 1; | プロパティの初期値 | |
{ get; } | 取得だけの自動プロパティ | |
{ get; init; } | init アクセサ | |
[field: SerializeField] | バッキングフィールドへの属性 | |
public virtual int V { get { … } } | 仮想プロパティ | 派生した型で上書きするには、基底の型を abstract にします。 |
public int this[int i] | 添字 | 角括弧に書いた値は、アクセサの引数として渡されます。 |
this[0] = 3; | 添字への書き込み | value に書き込む値が入り、添字は引数で受け取ります。 |
~C() { } | ファイナライザ | |
private volatile int V; | volatile | |
public readonly int Read() | 値型の readonly メンバ | 値型は渡すたびに複製されるので、付けても実行時の挙動は変わりません。 |
Add(1) / Add(1, 2) | 引数の数による選択 | |
Show(1) / Show("a") | 引数の型による選択 | |
Show(int) が Show(long) に勝つ | 変換の少ない候補の優先 | |
Sum(1, 2) | 可変長引数への展開 | |
Sum(int,int) が params に勝つ | 通常の候補の優先 | |
Add(1) | 既定の引数の省略 | |
Pick(1, 2) | 引数からの推論 | |
First(new int[] { 1 }) | 配列の要素からの推論 | |
Left(1, "a") | 2 つの型引数の推論 | |
Depth(new int[1][]) | 入れ子の配列からの推論 | |
true ? 1 : 2L | ?: の両側からの共通の型 | |
public struct Inner { ... } | 入れ子の型 | |
public partial class C | 分割して書く型 | |
abstract int Get(); / override | 抽象メソッドの実装 | |
virtual int Get() / override | 既定の実装の上書き | 基底の型は abstract でも具象でもかまいません。 |
base.Ring() | 基底の実装の呼び出し | 呼べるのは自分で書いた型の実装だけで、実行環境が定義するイベントの基底は呼べません。 |
非対応(11)
Section titled “非対応(11)”| 書き方 | 説明 | エラー | 理由 | 代替 |
|---|---|---|---|---|
public class Base : TsukimiBehaviour ... public class Leaf : Base | 同じファイルに具象の型を 2 つ書く | TUKI0109 | 設計 | ファイルを分ける(具象の型の継承そのものは通ります) |
public event System.Action Fired; | event を宣言する | TUKI0108 | 環境 | メソッドを直接呼ぶか、名前を指定して送る |
public event System.Action Fired { add { } remove { } } | add/remove アクセサを自分で定義する | TUKI0108 | 環境 | 同上 |
Fired?.Invoke() | event で通知する | TUKI0108 | 環境 | メソッドを直接呼ぶか、名前を指定して送る |
Fired += Handler | event を購読する | TUKI0108, TUKI0099 | 環境 | 同上 |
public static extern int Native() | 外部の実装を宣言する | TUKI0001 | 環境 | 実行環境のメソッドを呼ぶ |
Read(int v) と Read(in int v) を並べる | 渡し方の違いで候補を分ける | TUKI0001 | 未定 | 名前を変える。in 単独は使える(変数と引数の渡し方) |
public int Twice { get { … } set { … } }(struct の中) | 変更できる計算プロパティ(値型) | TUKI0001 | 未実装 | get だけにするか、メソッドにする(struct と record) |
public int Extra { get; set; }(record の中) | プロパティ(record) | TUKI0001 | 設計 | 位置パラメータにするか、メソッドにする |
c[0] = 1;(struct の中の添字) | 添字への書き込み(値型) | TUKI0001 | 未実装 | 新しい値を返すメソッドにするか、Behaviour 側の添字を使う |
panel[0](別の Behaviour の添字) | 別の Behaviour の添字を読む | TUKI0001 | 未定 | 相手側にメソッドを置いて、それを呼ぶ |
event | 宣言も書けません。宣言・購読・発火のどの行でも TUKI0108 です |
~C() と volatile | コンパイルも実行もでき、エラーも警告も出ませんが、書いても動作は変わりません |
| 型そのものを初期化するメンバ | 静的コンストラクタもモジュール初期化子も TUKI0001 です(フィールドの初期化と既定値) |
プロパティが対応するかどうかは、置く先とアクセサの 3 つの組み合わせで変わります。
| 置く先 | 自動プロパティ | 計算する(get だけ) | 計算する(set あり) |
|---|---|---|---|
| Behaviour | 書ける | 書ける | 書ける |
struct | 書ける | 書ける | 書けない |
record | init なら書ける | 書ける | 書けない |
| インタフェース | 書ける(実装する側も自動プロパティにする) | 書けない | — |
using UnityEngine;using Tsukimi;
public class MemField : TsukimiBehaviour{ private int count;
void Start() { Debug.Log(count); // => 0 }}宣言と同時の代入
Section titled “宣言と同時の代入”using UnityEngine;using Tsukimi;
public class MemFieldInitializer : TsukimiBehaviour{ private int count = 5;
void Start() { Debug.Log(count); // => 5 }}using UnityEngine;using Tsukimi;
public class MemConst : TsukimiBehaviour{ private const int Max = 10;
void Start() { Debug.Log(Max); // => 10 }}静的フィールド
Section titled “静的フィールド”インスタンスを作らずに読み書きします。
using UnityEngine;using Tsukimi;
public class MemStaticField : TsukimiBehaviour{ private static int Count;
void Start() { Count = 1; Debug.Log(Count); // => 1 }}静的な読み取り専用フィールド
Section titled “静的な読み取り専用フィールド”インスタンスを作らずに読み、あとから変更できません。
using UnityEngine;using Tsukimi;
public class MemStaticReadonly : TsukimiBehaviour{ private static readonly int Max = 10;
void Start() { Debug.Log(Max); // => 10 }}メソッドの宣言
Section titled “メソッドの宣言”using UnityEngine;using Tsukimi;
public class MemMethod : TsukimiBehaviour{ private void Do() { Debug.Log(1); } // => 1
void Start() { Do(); }}戻り値のあるメソッド
Section titled “戻り値のあるメソッド”using UnityEngine;using Tsukimi;
public class MemMethodReturn : TsukimiBehaviour{ private int Get() { return 1; }
void Start() { Debug.Log(Get()); // => 1 }}引数のあるメソッド
Section titled “引数のあるメソッド”using UnityEngine;using Tsukimi;
public class MemMethodParameters : TsukimiBehaviour{ private int Add(int a, int b) { return a + b; }
void Start() { Debug.Log(Add(1, 2)); // => 3 }}using UnityEngine;using Tsukimi;
public class MemDefaultArgument : TsukimiBehaviour{ private int Add(int a, int b = 2) { return a + b; }
void Start() { Debug.Log(Add(1)); // => 3 }}名前つき引数
Section titled “名前つき引数”using UnityEngine;using Tsukimi;
public class MemNamedArgument : TsukimiBehaviour{ private int Add(int a, int b) { return a + b; }
void Start() { Debug.Log(Add(b: 2, a: 1)); // => 3 }}オーバーロード
Section titled “オーバーロード”using UnityEngine;using Tsukimi;
public class MemOverload : TsukimiBehaviour{ private int Add(int a, int b) { return a + b; }
private float Add(float a, float b) { return a + b; }
void Start() { Debug.Log(Add(1, 2) + Add(1f, 2f)); // => 6 }}式形式のメソッド
Section titled “式形式のメソッド”using UnityEngine;using Tsukimi;
public class MemExpressionBodied : TsukimiBehaviour{ private int Twice(int n) => n * 2;
void Start() { Debug.Log(Twice(2)); // => 4 }}静的メソッド
Section titled “静的メソッド”using UnityEngine;using Tsukimi;
public class MemStaticMethod : TsukimiBehaviour{ private static int Zero() { return 0; }
void Start() { Debug.Log(Zero()); // => 0 }}自動プロパティ
Section titled “自動プロパティ”using UnityEngine;using Tsukimi;
public class MemAutoProperty : TsukimiBehaviour{ public int Value { get; set; }
void Start() { Value = 1; Debug.Log(Value); // => 1 }}計算するプロパティ
Section titled “計算するプロパティ”get の本体を自分で書くプロパティです。
using UnityEngine;using Tsukimi;
public class MemComputedProperty : TsukimiBehaviour{ private int n;
public int Doubled { get { return n * 2; } }
void Start() { n = 3; Debug.Log(Doubled); // => 6 }}取得と設定で異なる可視性
Section titled “取得と設定で異なる可視性”using UnityEngine;using Tsukimi;
public class MbAccessorAcc : TsukimiBehaviour{ void Start() { V = 1; Debug.Log(V); // => 1 }
public int V { get; private set; }}プロパティの初期値
Section titled “プロパティの初期値”using UnityEngine;using Tsukimi;
public class MbAutoPropInit : TsukimiBehaviour{ void Start() { Debug.Log(V); // => 1 }
public int V { get; set; } = 1;}取得だけの自動プロパティ
Section titled “取得だけの自動プロパティ”using UnityEngine;using Tsukimi;
public class MbGetterOnly : TsukimiBehaviour{ void Start() { Debug.Log(V); // => 0 }
public int V { get; }}init アクセサ
Section titled “init アクセサ”using UnityEngine;using Tsukimi;
public class MbInitAccessor : TsukimiBehaviour{ void Start() { Debug.Log(V); // => 0 }
public int V { get; init; }}バッキングフィールドへの属性
Section titled “バッキングフィールドへの属性”using UnityEngine;using Tsukimi;
public class MbFieldAttr : TsukimiBehaviour{ void Start() { Debug.Log(V); // => 0 }
[field: SerializeField] public int V { get; set; }}仮想プロパティ
Section titled “仮想プロパティ”virtual を付けたプロパティです。
using UnityEngine;using Tsukimi;
public class MbVirtualProp : TsukimiBehaviour{ void Start() { Debug.Log(V); // => 1 }
public virtual int V { get { return 1; } }}this[int i] を宣言すると、その型の値を v[i] と書いて読めます。
using UnityEngine;using Tsukimi;
public class MbIndexer : TsukimiBehaviour{ void Start() { Debug.Log(this[2]); // => 20 }
public int this[int i] { get { return i * 10; } }}添字への書き込み
Section titled “添字への書き込み”set も書くと v[i] = x と書いて書き込めます。
using UnityEngine;using Tsukimi;
public class MbIndexerSet : TsukimiBehaviour{ private int a; private int b;
void Start() { this[0] = 3; this[1] = 4; Debug.Log(this[0] * 10 + this[1]); // => 34 }
public int this[int i] { get { return i == 0 ? a : b; } set { if (i == 0) { a = value; } else { b = value; } } }}対応しているが効果の無い構文
Section titled “対応しているが効果の無い構文”ファイナライザ
Section titled “ファイナライザ”ファイナライザを呼ぶ仕組みが実行環境に無いので、本体は一度も実行されません。
using UnityEngine;using Tsukimi;
public class MbFinalizer : TsukimiBehaviour{ void Start() { Debug.Log(1); // => 1 }
~MbFinalizer() { }}volatile
Section titled “volatile”同時に実行される流れが無いので、volatile を付けても読み書きの意味は変わりません。
using UnityEngine;using Tsukimi;
public class MbVolatile : TsukimiBehaviour{ void Start() { Debug.Log(V); // => 0 }
private volatile int V;}値型の readonly メンバ
Section titled “値型の readonly メンバ”値を変更しないメンバに付けられます。
using UnityEngine;using Tsukimi;
public struct Point { public int X; public readonly int Read() { return X; } }public class MbReadonlyMember : TsukimiBehaviour{ void Start() { Point p = new Point(); Debug.Log(p.Read()); // => 0 }}候補の選択規則
Section titled “候補の選択規則”引数の数による選択
Section titled “引数の数による選択”using UnityEngine;using Tsukimi;
public class OvByArity : TsukimiBehaviour{ void Start() { Debug.Log(Add(1)); // => 1 Debug.Log(Add(1, 2)); // => 3 }
private int Add(int a) { return a; } private int Add(int a, int b) { return a + b; }}引数の型による選択
Section titled “引数の型による選択”using UnityEngine;using Tsukimi;
public class OvByType : TsukimiBehaviour{ void Start() { Debug.Log(Show(1)); // => 1 Debug.Log(Show("a")); // => 2 }
private int Show(int a) { return 1; } private int Show(string a) { return 2; }}変換の少ない候補の優先
Section titled “変換の少ない候補の優先”using UnityEngine;using Tsukimi;
public class OvBetterConv : TsukimiBehaviour{ void Start() { Debug.Log(Show(1)); // => 2 }
private int Show(long a) { return 1; } private int Show(int a) { return 2; }}可変長引数への展開
Section titled “可変長引数への展開”using UnityEngine;using Tsukimi;
public class OvExpanded : TsukimiBehaviour{ void Start() { Debug.Log(Sum(1, 2)); // => 2 Debug.Log(Sum(new int[] { 1, 2 })); // => 2 }
private int Sum(params int[] xs) { return xs.Length; }}通常の候補の優先
Section titled “通常の候補の優先”using UnityEngine;using Tsukimi;
public class OvNormalBeatsParams : TsukimiBehaviour{ void Start() { Debug.Log(Sum(1, 2)); // => 1 }
private int Sum(int a, int b) { return 1; } private int Sum(params int[] xs) { return 2; }}既定の引数の省略
Section titled “既定の引数の省略”using UnityEngine;using Tsukimi;
public class OvDefaultArg : TsukimiBehaviour{ void Start() { Debug.Log(Add(1)); // => 3 Debug.Log(Add(1, 5)); // => 6 }
private int Add(int a, int b = 2) { return a + b; }}型引数の推論
Section titled “型引数の推論”引数からの推論
Section titled “引数からの推論”using UnityEngine;using Tsukimi;
public class OvInferArgs : TsukimiBehaviour{ void Start() { Debug.Log(Pick(1, 2)); // => 1 }
private T Pick<T>(T a, T b) { return a; }}配列の要素からの推論
Section titled “配列の要素からの推論”using UnityEngine;using Tsukimi;
public class OvInferLower : TsukimiBehaviour{ void Start() { Debug.Log(First(new int[] { 1 })); // => 1 }
private T First<T>(T[] xs) { return xs[0]; }}2 つの型引数の推論
Section titled “2 つの型引数の推論”using UnityEngine;using Tsukimi;
public class OvInferTwo : TsukimiBehaviour{ void Start() { Debug.Log(Left(1, "a")); // => 1 }
private T1 Left<T1, T2>(T1 a, T2 b) { return a; }}入れ子の配列からの推論
Section titled “入れ子の配列からの推論”T[][] のような入れ子の配列からも、要素の型が決まります。
using UnityEngine;using Tsukimi;
public class OvInferNested : TsukimiBehaviour{ void Start() { Debug.Log(Depth(new int[1][])); // => 1 }
private int Depth<T>(T[][] xs) { return xs.Length; }}?: の両側からの共通の型
Section titled “?: の両側からの共通の型”using UnityEngine;using Tsukimi;
public class OvBestCommon : TsukimiBehaviour{ void Start() { long v = true ? 1 : 2L; Debug.Log(v); // => 1 }}継承と入れ子
Section titled “継承と入れ子”using UnityEngine;using Tsukimi;
public class MemNestedType : TsukimiBehaviour{ public struct Inner { public int V; }
void Start() { Inner i = new Inner(); Debug.Log(i.V); // => 0 }}分割して書く型
Section titled “分割して書く型”using UnityEngine;using Tsukimi;
public partial class R_part : TsukimiBehaviour{ void Start() { Debug.Log(Helper()); }}
public partial class R_part{ private int extra;
int Helper() { extra = 41; return extra + 1; }}抽象メソッドの実装
Section titled “抽象メソッドの実装”using UnityEngine;using Tsukimi;
public abstract class MemAbstractBase : TsukimiBehaviour{ public abstract int Get();}
public class MemAbstractLeaf : MemAbstractBase{ public override int Get() { return 1; }
void Start() { Debug.Log(Get()); // => 1 }}既定の実装の上書き
Section titled “既定の実装の上書き”virtual のメソッドを override で上書きできます。
using UnityEngine;using Tsukimi;
public abstract class MemVirtualBase : TsukimiBehaviour{ public virtual int Get() { return 0; }}
public class MemVirtualLeaf : MemVirtualBase{ public override int Get() { return 1; }
void Start() { Debug.Log(Get()); // => 1 }}基底の実装の呼び出し
Section titled “基底の実装の呼び出し”override した側から、基底に書いた実装を base で呼べます。
using UnityEngine;using Tsukimi;
public abstract class MemBaseCallBase : TsukimiBehaviour{ public int hits; public virtual void Ring() { hits = hits + 1; }}
public class MemBaseCallLeaf : MemBaseCallBase{ public int extra;
public override void Ring() { base.Ring(); extra = extra + 1; }
void Start() { Ring(); Debug.Log(hits); // => 1 Debug.Log(extra); // => 1 }}