[C# class] インデクサー(indexer)について

クラスメンバーのインデクサーについてです。

インデクサーの機能を使うと配列と同じようにクラスに対して角かっこ [ ] を使い、要素の取得・設定をすることが出来るようになります。

スポンサーリンク

インデクサの使い方

インデクサの定義はこんな感じです。

アクセスレベル 戻り値の型 this[インデックスの型 インデックス名]
{
    アクセスレベル get
    {
        // get は [ ] で要素を取得しようとするときに呼ばれる
        // return を使って呼び出し元に値を返す(型は「戻り値の型」で指定した型)
    }
    アクセスレベル set
    {
        // set は [ ] で要素を設定しようとするときに呼ばれる
        // value という名前の変数に呼び出し元で指定された値が設定されている
        // valueの型は「戻り値の型」で指定した型
    }
}

アクセスレベルにはprivate、publicなどを指定します。
getは外部に公開、setは内部からのみ、などそれぞれ指定することができます。
インデクサ自体のアクセスレベルを省略するとprivate
get、setのアクセスレベルを省略するとpublicになるみたいです。

インデックスの型は [ ] で指定する添え字の型を指定します。
string型にした場合は a[“test”] のように [ ] の中にstring型を指定して要素にアクセスします。

インデックス名はget、set内で使う添え字の名前です。

get は[ ] で要素を取得しようとするときに呼ばれます。 { } 内に returnを使い値を返す処理を書きます。

set は [ ] で要素を設定しようとするときに呼ばれます。{ } 内に処理を書きます。setの{ } 内ではvalueという変数に呼び出し側で指定された値が入っています。

get、setは必ず両方定義する必要はありません。getだけにして読み取り専用setだけにして書き込み専用のインデクサーを定義ことができます。

サンプルコードです。

using System;
using System.Collections.Generic;

class Program
{
    public static void Main()
    {
        var cls = new Sample();

        // [ ] を使って要素を取得しようとするとgetが呼ばれる
        Console.WriteLine(cls[2]);

        // [ ] を使って要素を設定しようとするとsetが呼ばれる
        cls[2] = "z";
        Console.WriteLine(cls[2]);
    }
}

class Sample 
{
    // [ ] でアクセスがあった時に読み書きする用のリスト
    List<string> list = new List<string> { "a", "b", "c", "d" };

    // これがインデクサー
    public string this[int i] 
    {
        // get は [ ] で要素を取得しようとするときに呼ばれる
        get { return this.list[i]; }

        // set は [ ] で要素を設定しようとするときに呼ばれる
        set { this.list[i] = value; }
    }
}

出力結果はこんな感じです。

c
z

get、setの処理が1つの式の場合、=> を使って処理を書くことができます。

using System;
using System.Collections.Generic;

class Program
{
    public static void Main()
    {
        var cls = new Sample();
        Console.WriteLine(cls[2]);
    }
}

class Sample 
{
    // [ ] でアクセスがあった時に読み書きする用のリスト
    List<string> list = new List<string> { "a", "b", "c", "d" };

    // これがインデクサー
    public string this[int i] 
    {
        get => list[i];
        set => list[i] = value;
    }
}
スポンサーリンク

インデックスの型について

上の説明でも書きましたが、インデックスの型は整数(int)である必要はありません。

string型のインデクサーのサンプルです。

using System;
using System.Collections.Generic;

class Program
{
    public static void Main()
    {
        var cls = new Sample();

        cls["a"] = 10;
        cls["b"] = 20;

        Console.WriteLine(cls["a"]);    // 10
        Console.WriteLine(cls["b"]);    // 20
    }
}

class Sample
{
    Dictionary<string, int> dic = new Dictionary<string, int>();

    // これがインデクサー
    public int this[string s] 
    {
        get => this.dic[s];
        set => this.dic[s] = value;
    }
}
スポンサーリンク

複数のインデックスを指定するインデクサー

複数のインデックスを指定するインデクサーも定義できます。

using System;
using System.Collections.Generic;

class Program
{
    public static void Main()
    {
        var cls = new Sample();
        Console.WriteLine(cls[2, 3]);
    }
}

class Sample
{
    // [ ] でアクセスがあった時に読み書きする用
    List<List<string>> list = new List<List<string>> { 
        new List<string> { "a", "b", "c", "d" },
        new List<string> { "e", "f", "g", "h" },
        new List<string> { "i", "j", "k", "l" },
    };

    // これがインデクサー
    public string this[int i, int j] 
    {
        get => list[i][j];
        set => list[i][j] = value;
    }
}
スポンサーリンク

読み取り専用のインデクサー

読み取り専用のインデクサーで値を返すだけなど処理が1つ場合にgetキーワードを省略して書くことができます。

using System;
using System.Collections.Generic;

class Program
{
    public static void Main()
    {
        var cls = new Sample();
        Console.WriteLine(cls[2]);
    }
}

class Sample
{
    // [ ] でアクセスがあった時に読み書きする用のリスト
    List<string> list = new List<string> { "a", "b", "c", "d" };

    // 読み取り専用(getだけ)のインデクサー
    public string this[int i] => this.list[i];
}

C# プログラミング講座に戻る

コメント

タイトルとURLをコピーしました