C#にも「演算子のオーバーロード」が用意されています。
角かっこ[]も演算子として扱うことができます。
角かっこは、「添字演算子」=「インデクサ」とよばれ、オーバーロードして定義することが出来ます。
インデクサーの定義
インデクサの定義は、プロパティと似た実装になります。
アクセスレベル 戻り値の型 this[添字の型 添字] { set { // // ここに値の変更時の処理を書く。 // 添字が使える以外はプロパティと同じ。 // } get { // // ここに値の取得時の処理を書く。 // こっちも添字が使える以外はプロパティと同じ。 // 値はreturnキーワードを用いて返す。 // } }
setで値を設定、getで値を取得となります。
ですのでsetの’value’、取得での戻り値の型は、「インデクサを用いて取り扱うデータの型」となります。
インデクサをオーバーロードしたクラス
インデクサをオーバーロードしたクラスを実装してみます。
public class IndexTestClass { private int[] _item = new int[] { 1,2,3 }; public int this[int index] { set { _item[index] = value; } get { return this._item[index]; } } }
このクラスの動作を確認するサンプルプログラム
static void Main(string[] args) { IndexTestClass obj = new IndexerSample.IndexTestClass(); for(int i = 0; i < 3; i++) { obj[i] = (i * 100); } // for (int i = 0; i < 3; i++) { Console.WriteLine(string.Format("{0}={1}", i, obj[i])); } }
作成したクラス’IndexTestClass’のメンバ_itemを配列と同じようにアクセスができます。
少し違ったインデクサ(string型でアクセス)
インデクサにstring型にした場合は下記のようになります。
public class IndexTestClass { private Dictionary<string, int> _item = new Dictionary<string, int>(); public int this[string key] { set { this._item[key] = value; } get { return this._item[key]; } } }
メンバ_itemの型をDictionary<string, int>にしています。
動作を確認するためのプログラム
static void Main(string[] args) { string[] keys = { "key1", "key2", "key3" }; IndexTestClass obj = new IndexerSample.IndexTestClass(); for(int i = 0; i < 3; i++) { string key = keys[i]; obj[key] = (i * 100); } // for (int i = 0; i < 3; i++) { string key = keys[i]; Console.WriteLine(string.Format("{0}={1}", key, obj[key])); } }
応用技
上記2種類のインデクサを両方扱えるようにオーバーロードしてみます。
public class IndexTestClass { private Dictionary<string, int> _item = new Dictionary<string, int>(); public int this[string key] { set { this._item[key] = value; } get { return this._item[key]; } } public int this[int index] { set { int i = 0; foreach(string key in _item.Keys) { if(i == index) { this._item[key] = value; break; } i++; } } get { int i = 0; foreach (string key in _item.Keys) { if (i == index) { return this._item[key]; } i++; } throw new IndexOutOfRangeException(); } } }
両方のインデクサで動作を確認するためのプログラム
static void Main(string[] args) { string[] keys = { "key1", "key2", "key3" }; IndexTestClass obj = new IndexerSample.IndexTestClass(); // string型のインデクサアクセス for (int i = 0; i < 3; i++) { string key = keys[i]; obj[key] = (i * 100); } // for (int i = 0; i < 3; i++) { string key = keys[i]; Console.WriteLine(string.Format("{0}={1}", key, obj[key])); } // int型のインデクサアクセス for (int i = 0; i < 3; i++) { obj[i] = (i * 1000); } // for (int i = 0; i < 3; i++) { Console.WriteLine(string.Format("{0}={1}", i, obj[i])); } }
こうすると、Dictionaryで、キーを用いたアクセスと通常の配列と同じようなインデックス値によるアクセスができます。