白猫のメモ帳

C#とかJavaとかJavaScriptとかHTMLとか機械学習とか。

Java使いがC#を勉強する その④ インデクサ

こんばんは。

なんだか雪みたいなものが降りましたね。
寒いわけです。

さて、前回はプロパティについて書きましたが、
今回はその延長でインデクサについて見ていきます。

インデクサ


インデクサはインスタンスに添え字を指定してアクセスできる機能です。

Javaではリストから値を取得する場合には、

String hoge = list.get(1);

のように書きますが、C#ではインデクサを使ってこうやって書けます。

string hoge = list[1];

配列っぽいですね。

インデクサの文法はプロパティと似ています。
こんな風に定義すると、

class Hoge
{
    private string[] ary;

    public Hoge(int size)
    {
        this.ary = new string[size];
    }

    public string this[int i]
    {
        get { return ary[i]; }
        set { ary[i] = value; }
    }
}

普通のオブジェクトも配列みたいにアクセスできます。

Hoge hoge = new Hoge(1);
hoge[0] = "ふがふが";


インデクサ引数の定義に型があることからもわかりますが、
int以外にも指定できるため、連想配列みたいにも使えます。

public int this[string str]
{
    get { /* なんか返す */ }
    set { /* なんかする */ }
}

と定義すると、

Hoge hoge = new Hoge();
hoge["ほげほげ"] = 3;

みたいに使えるわけですね。

はて、使い道は・・・?


便利そうですが、どんな時に使うのかがよくわかりません。
引数を取って戻り値を返す、それはメソッドというやつじゃないか。

うーん。

class CharPicker
{
    private char[] ary;

    public CharPicker(string str)
    {
        this.ary = str.ToCharArray();
    }

    public char this[int i] => this.ary[i];
}

こんなのを作って、

CharPicker cp = new CharPicker("あいうえお");
Console.WriteLine(cp[2]); // う

いや…うれしいかなこれ。

Zip作ってみるとか?

class Zip<T, S>
{
    private IList<T> list1;
    private IList<S> list2;

    public Zip(IList<T> list1, IList<S> list2)
    {
        this.list1 = list1;
        this.list2 = list2;
    }

    public int Count => Math.Min(list1.Count, list2.Count);

    public Tuple<T, S> this[int i] => Tuple.Create(this.list1[i], this.list2[i]);
}

で、

var list1 = new List<string> { "あ", "い", "う" };
var list2 = new List<int> { 1, 2, 3 };

var zip = new Zip<string, int>(list1, list2);
for (int i = 0; i < zip.Count; i++)
{
    Console.WriteLine(zip[i]);
}

うーん。