問題
百聞は一見に如かず。たとえば、test1~test4までフィールドがあるとき「こうすれば楽に変数の中身を全て取り出せる」と思うことがあります(図1)。
変数名に変数を使いたい場合というのが数年に一度あり、そのたびいつもやり方を忘れてしまうのでメモしておきます。
アプローチ
リフレクションを使います。次のようにコードを書けば、図2に示すように、Unityのコンソールに “this”, “is”, “a”, “pen” と表示されます。
using System.Reflection;
using UnityEngine;
public class Variable_Test : MonoBehaviour
{
private string test1 = "this";
private string test2 = "is";
private string test3 = "a";
private string test4 = "pen";
void Start()
{
for (int i = 1; i < 5; i++)
{
var test = GetType().GetField("test" + i, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
Debug.Log(test.GetValue(this));
}
}
}
太字の部分が(リファクタリングできなくて)気に食わない人は、”test” という名前の変数を作って
FiledInfo test;
test = GetType().GetField(nameof(test) + i, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
“nameof(test)” などとすれば良いです。
おまけ
ちなみにReflectionはパフォーマンス的に非常に悪いので、本番用でこの手法は取りません。変数の中身を配列に突っ込んでforeachで回すケースが多いです。
string[] tests = new[]{test1, test2, test3, test4};
foreach(var test in tests){
Debug.Log(test);
}
さらにReflectionの機能の一部はWebGLで使えません。その意味でも本記事のアプローチは使い道が限られています。
参考文献