【Unity】Unityで使えるC#7の主要機能まとめ!isやswitchのスマートな書き方やタプルの追加など

Unity2018.3から使えるようになったC#7の機能を一通りまとめました。

Unity2019.2.6

isで型チェックしてそのまま変数に格納

まずis演算子を使うと型の判定ができます。

if (obj is Texture2D) {}

ここで、このように型を判定した後にその型にそのままキャストして処理を行いたいことがよくあります。
これまでのC#では、以下のようにas演算子でキャストした後にnullチェックを使う必要がありました。

var texture = obj as Texture2D;
if (texture != null) {
    Debug.Log($"{texture.width} / {texture.height}");
}

C#7では、以下のようにisの後に変数名を書くことで、その型にキャストした値を扱えるようになりました。

if (obj is Texture2D texture) {
    Debug.Log($"{texture.width} / {texture.height}");
}

switchのcase句で指定の型かどうかを判定できるように

switch内のcaseで「特定の型だったら」という判定ができるようになりました。
たとえばint型だったときのみ入るcaseを定義するには以下のように書きます。

object obj;

switch (obj) {
case int value:
    Debug.Log(value);
    break;
default:
    break;
}

さらに以下のようにwhenで条件を指定することもできます。

switch (obj) {
case int value when value >= 10:
    Debug.Log(value);
    break;
default:
    break;
}

タプル

タプルを使うと匿名の型を作れます。
たとえば以下のようにint型とstring型を持つ型を定義できます。

var taro = (1, "太郎");
var jiro = (2, "次郎");

Debug.Log($"{taro.Item1} : {taro.Item2}\n{jiro.Item1} : {jiro.Item2}");

上記ではタプルの各要素にitem1やitem2といった名前でアクセスしていますが、明示的に名前を付けることもできます。

(int id, string name) taro = (1, "太郎");
(int id, string name) jiro = (2, "次郎");

Debug.Log($"{taro.id} : {taro.name}\n{jiro.id} : {jiro.name}");

タプルの主な用途としては引数の戻り値がありそうです。

private void Start()
{
    var taro = GetTaro();
    Debug.Log($"{taro.id} : {taro.name}");
}

private (int id, string name) GetTaro()
{
    return (1, "太郎");
}

タプルを受け取るときには上記のようにタプル型のまま受け取ることもできれば、
下記のようにタプルのそれぞれの要素に対して変数を割り当てることもできます。

private void Start()
{
    var (taroId, taroName) = GetTaro();
    Debug.Log($"{taroId} : {taroName}");
}

private (int id, string name) GetTaro()
{
    return (1, "太郎");
}

ローカル関数

C#7からは関数の中に関数が書けるようになりました。
これをローカル関数と呼びます。書き方は普通の関数と同様です。

private void Start()
{
    int add(int a, int b) => a + b;

    Debug.Log(add(1, 10));
}

コンストラクタやプロパティなどが一行で書けるように

C#6では短い関数が一行で簡潔に書けるようになりました。

public void Log(int value) => Debug.Log(value);

C#7からは、コンストラクタやデストラクタ、プロパティなどもこのような書き方に対応しました。

public class Example
{
    private int _x;

    public int X 
    {
        get => _x;
        set => _x = value;
    }

    public Example(int value) => _x = value;
}

戻り値にもrefを使えるように

まず、ref修飾子を使うと値型でも参照渡しをすることができます。

public void Start()
{
    var value = 10;
        
    Increment(ref value);
    Increment(ref value);
        
    Debug.Log(value); // 12
}

public void Increment(ref int value) => value++;

C#7からは、関数の戻り値にもこのrefを使えるようになりました。

public void Start()
{
    var src = 10;
    var dst = -1;
    
    ref var copied = ref ShallowCopy(ref src, ref dst);
        
    Debug.Log(copied); // 10
}

// dstにsrcの参照を入れてdstを参照渡しで返す
public ref int ShallowCopy(ref int src, ref int dst)
{
    dst = src;
    return ref dst;
}

関連

light11.hatenadiary.com