コンテンツにスキップ

メンバ

書き方説明
private int count;フィールド
private int count = 5;宣言と同時の代入
private const int Max = 10;定数
private static int Count;静的フィールド
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; } }計算するプロパティ
{ get; private set; }取得と設定で異なる可視性
{ get; set; } = 1;プロパティの初期値
{ get; }取得だけの自動プロパティ
{ get; init; }init アクセサ
[field: SerializeField]裏のフィールドへの属性
public virtual int V { get { … } }仮想プロパティ
public int this[int i]添字
this[0] = 3;添字への書き込み
public event System.Action Fired;event の宣言
event … { add { } remove { } }購読の受け口の記述
~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既定の実装の上書き
書き方説明エラー理由代わりに
public class Base : TsukimiBehaviour ... public class Leaf : Base具象の型を継承するTUKI0109未定基底を abstract にする
Fired?.Invoke()event で通知するTUKI0108環境メソッドを直接呼ぶか、名前を指定して送る
Fired += Handlerevent を購読する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未実装新しい値を返すメソッドにするか、ふるまい側の添字を使う
panel[0](別のふるまいの添字)別のふるまいの添字を読むTUKI0001未定相手側にメソッドを置いて、それを呼ぶ
event宣言だけがコンパイルを通ります。Fired += Handler と書いた行と、Fired?.Invoke() と書いた行で TUKI0108 が出ます。

~C()volatile は、コンパイルも実行も通ります。エラーも警告も出ませんが、書いても動きは変わりません。型そのものを初期化するメンバ(静的コンストラクタ・モジュール初期化子)も走りません(初期化と実行順序)。

プロパティが通るかどうかは、置く先とアクセサの形で変わります。

置く先自動プロパティ計算する(get だけ)計算する(set あり)
Behaviour書ける書ける書ける
struct書ける書ける書けない
record書けない書けない書けない
インタフェース書ける(実装する側も自動プロパティにする)書けない
using UnityEngine;
using Tsukimi;
public class MemField : TsukimiBehaviour
{
private int count;
void Start()
{
Debug.Log(count); // => 0
}
}
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
}
}

インスタンスを作らずに読み書きします。値はふるまいの実体ごとに別で、実体のあいだで共有されません。

using UnityEngine;
using Tsukimi;
public class MemStaticField : TsukimiBehaviour
{
private static int Count;
void Start()
{
Count = 1;
Debug.Log(Count); // => 1
}
}

静的な読み取り専用フィールド

Section titled “静的な読み取り専用フィールド”

static readonly は書けますが、型が struct のものは通りません(struct と record)。

using UnityEngine;
using Tsukimi;
public class MemStaticReadonly : TsukimiBehaviour
{
private static readonly int Max = 10;
void Start()
{
Debug.Log(Max); // => 10
}
}
using UnityEngine;
using Tsukimi;
public class MemMethod : TsukimiBehaviour
{
private void Do() { Debug.Log(1); } // => 1
void Start()
{
Do();
}
}
using UnityEngine;
using Tsukimi;
public class MemMethodReturn : TsukimiBehaviour
{
private int Get() { return 1; }
void Start()
{
Debug.Log(Get()); // => 1
}
}
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
}
}
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
}
}
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
}
}
using UnityEngine;
using Tsukimi;
public class MemExpressionBodied : TsukimiBehaviour
{
private int Twice(int n) => n * 2;
void Start()
{
Debug.Log(Twice(2)); // => 4
}
}
using UnityEngine;
using Tsukimi;
public class MemStaticMethod : TsukimiBehaviour
{
private static int Zero() { return 0; }
void Start()
{
Debug.Log(Zero()); // => 0
}
}
using UnityEngine;
using Tsukimi;
public class MemAutoProperty : TsukimiBehaviour
{
public int Value { get; set; }
void Start()
{
Value = 1;
Debug.Log(Value); // => 1
}
}

get の本体を自分で書くプロパティです。struct の中では set を書けません(struct と record)。

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
}
}
using UnityEngine;
using Tsukimi;
public class MbAccessorAcc : TsukimiBehaviour
{
void Start()
{
V = 1;
Debug.Log(V); // => 1
}
public int V { get; private set; }
}
using UnityEngine;
using Tsukimi;
public class MbAutoPropInit : TsukimiBehaviour
{
void Start()
{
Debug.Log(V); // => 1
}
public int V { get; set; } = 1;
}
using UnityEngine;
using Tsukimi;
public class MbGetterOnly : TsukimiBehaviour
{
void Start()
{
Debug.Log(V); // => 0
}
public int V { get; }
}
using UnityEngine;
using Tsukimi;
public class MbInitAccessor : TsukimiBehaviour
{
void Start()
{
Debug.Log(V); // => 0
}
public int V { get; init; }
}
using UnityEngine;
using Tsukimi;
public class MbFieldAttr : TsukimiBehaviour
{
void Start()
{
Debug.Log(V); // => 0
}
[field: SerializeField]
public int V { get; set; }
}

virtual を付けたプロパティです。派生した型で上書きするには、基底の型を abstract にします。

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

set も書くと v[i] = x の形で書き込めます。value に書き込む値が入り、添字は引数で受け取ります。

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

event の宣言はコンパイルを通ります。購読と発火の行を書くと TUKI0108 が出ます。

using UnityEngine;
using Tsukimi;
public class MbEventField : TsukimiBehaviour
{
void Start()
{
Debug.Log(1); // => 1
}
public event System.Action Fired;
}

addremove を自分で書く形も、宣言だけは通ります。

using UnityEngine;
using Tsukimi;
public class MbEventAcc : TsukimiBehaviour
{
void Start()
{
Debug.Log(1); // => 1
}
public event System.Action Fired { add { } remove { } }
}

ファイナライザを呼ぶ仕組みが実行環境に無いので、本体は一度も走りません。

using UnityEngine;
using Tsukimi;
public class MbFinalizer : TsukimiBehaviour
{
void Start()
{
Debug.Log(1); // => 1
}
~MbFinalizer() { }
}

同時に動く実行の流れが無いので、volatile を付けても読み書きの意味は変わりません。

using UnityEngine;
using Tsukimi;
public class MbVolatile : TsukimiBehaviour
{
void Start()
{
Debug.Log(V); // => 0
}
private volatile int V;
}

値を書き換えないメンバに付けられます。値型は渡すたびに複製されるので、付けても実行時のふるまいは変わりません。

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

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; }
}
using UnityEngine;
using Tsukimi;
public class OvBestCommon : TsukimiBehaviour
{
void Start()
{
long v = true ? 1 : 2L;
Debug.Log(v); // => 1
}
}
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
}
}
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;
}
}
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
}
}

virtual のメソッドを override で上書きできます。基底の型は abstract である必要があります。

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