見出し画像

[Unity]C#で関数の引数を読み取り専用にしたい!

コード書いとる?

C#で関数の引数を読み取り専用(readonly)にしたくて困ったメモ書き。ここはnote。

C#変数書き換え問題

C#で書いてていつも思ってるんだけど引数…とくに配列を変更不可にしたいんだけどできないんだよな〜🤔

void f(int[] array)
{
  // arrayを書き換えてるのかどうか引数を見ただけでわからない!
  array[0] = 2;
}

引数にinをつける方法はあるのですが…配列やクラス内の値の変更を阻止できない。惜しい!😅

void f(in int value, in int[] array)
{
  // これはエラーにできる
  value = 1;
  // これをエラーにできない
  array[0] = 1;
}    

C++なら引数にconstをつければ良いのですがC#ではこれはできない。

void f(const int array[])
{
  // これがビルドエラーになる
  array[0] = 2;
}

自分ひとりでゲーム作ってても次第にコードが複雑になってゆきそして!そうだわ〜あっちの関数で中身書き換えてるわ〜!ってなる😂

C#だと関数の引数を見ただけでは内容が変更されるのかどうなのかわからない🥺

自分で書いたコードでさえ3日後に見たらもうわからない🥺

と思っていたらありました

void f(IReadOnlyList<int> array)
{
  // ランダムアクセスOK
  Debug.Log(array[0]);
  // エラーにできる
  array[0] = 2;
}

引数の型をIReadOnlyListにすれば良さそう。引数は関数内で変更しないと明示しつつさらに配列とListの区別がなくなる...これはイイ!

// 配列とListの区別なく引数にできる〜
f(new int[]{0, 1, 2});
f(new List<int>(){0, 1, 2});

ランダムアクセスしないなら

void f(IReadOnlyCollection<int> array)
{
  foreach (var a in array)
  {
    Debug.Log(a);
  }
} 

foreachなどで列挙するだけならIReadOnlyCollectionでもよい。

列挙可能であれば配列以外にListでもHashSetでもQueueでもStackでも同じ関数の引数として渡せる!これも便利!

もっと早く言ってよぉ〜🥺

拙作しまのアヒルちゃん製作中に関数の引数をint[]→List<int>と変更してめんどいなと思っていただけに!

ではまた次回!

いいなと思ったら応援しよう!