クラスにデフォルトプロパティ (既定のインデクサのプロパティ) を実装する - C#

クラスにデフォルトプロパティを実装するコードを紹介します。

概要

Listクラスなど、オブジェクト自身にインデクサを記述して、値を取得したり代入できるクラスがあります。
この記事では、既定のインデクサのプロパティを実装してオブジェクトに添え字を記述してプロパティにアクセスできるクラスを実装します。
クラスのデフォルトプロパティを実装する場合は this を利用します。

書式

  public (型名) this[(型名) index]
  {
    get{
    }
    set{
    }
  }

プログラム例1: 添え字の型がint型の場合

UI

下図のフォームを作成します。ボタンと複数行のテキストボックスを配置します。

コード

下記のコードを記述します。
MyClass.cs
using System;
using System.Collections.Generic;
using System.Text;

namespace ClassDefaultProperty
{
  public class MyClass
  {
    private string[] myStrings;
    public MyClass(int capacity)
    {
      myStrings = new string[capacity];
    }

    public string this[int index]
    {
      get
      {
        return myStrings[index];
      }
      set
      {
        myStrings[index] = value;
      }
    }
  }
}
FormMain.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ClassDefaultProperty
{
  public partial class FormMain : Form
  {
    public FormMain()
    {
      InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    private void button1_Click(object sender, EventArgs e)
    {
      MyClass mc = new MyClass(3);
      mc[0] = "ぺんぎんクッキー";
      mc[1] = "らくだキャラメル";
      mc[2] = "しろくまアイス";

      textBox1.Text += mc[0] + "\r\n";
      textBox1.Text += mc[1] + "\r\n";
      textBox1.Text += mc[2] + "\r\n";
    }
  }
}

解説

MyClassの下記コードがデフォルトプロパティになります。
   public string this[int index]
    {
      get
      {
        return myStrings[index];
      }
      set
      {
        myStrings[index] = value;
      }
    }

下記のコードがクラスのデフォルトプロパティの利用コードです。
はじめに MyClassオブジェクトを作成します。MyClassオブジェクトに添え字をつけて文字列を代入します。 代入後に、MyClassオブジェクトに添え字をつけて参照した値をテキストボックスに表示します。
    private void button1_Click(object sender, EventArgs e)
    {
      MyClass mc = new MyClass(3);
      mc[0] = "ぺんぎんクッキー";
      mc[1] = "らくだキャラメル";
      mc[2] = "しろくまアイス";

      textBox1.Text += mc[0] + "\r\n";
      textBox1.Text += mc[1] + "\r\n";
      textBox1.Text += mc[2] + "\r\n";
    }

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。


[button1]をクリックします。下図のメッセージがテキストボックスに表示されます。 コードでクラスのデフォルトプロパティに代入した文字列を参照してテキストボックスに表示できていることが確認できます。

プログラム例2: 添え字の型がstirng型の場合

UI

下図のフォームを作成します。ボタンと複数行のテキストボックスを配置します。

コード

下記のコードを記述します。
MyClass2.cs
using System;
using System.Collections.Generic;
using System.Text;

namespace ClassDefaultProperty
{
  public class MyClass2
  {
    class ItemType{
      public string key;
      public int value;
    }

    private List<ItemType> myItem;
    public MyClass2()
    {
      myItem = new List<ItemType>();
    }

    public int this[string key_string]
    {
      get
      {
        foreach (ItemType t in myItem) {
          if (t.key == key_string) {
            return t.value;
          }
        }
        return -1;
      }
      set
      {
        ItemType it = new ItemType();
        it.key = key_string;
        it.value = value;
        myItem.Add(it);
      }
    }
  }

}
FormMain.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ClassDefaultProperty
{
  public partial class FormMain : Form
  {
    public FormMain()
    {
      InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    private void button2_Click(object sender, EventArgs e)
    {
      MyClass2 mc2 = new MyClass2();
      mc2["Penguin"] = 200;
      mc2["Duck"] = 30;
      mc2["Bear"] = 420;

      textBox1.Text += mc2["Bear"].ToString() + "\r\n";
      textBox1.Text += mc2["Duck"].ToString() + "\r\n";
      textBox1.Text += mc2["Penguin"].ToString() + "\r\n";
      textBox1.Text += mc2["Whale"].ToString() + "\r\n";
    }
  }
}

解説

MyClass2では内部でItemTypeクラスを宣言します。文字列型のkey と 整数型のvalue のメンバを持つクラスです。
宣言したItemTypeクラスのリストである myItem オブジェクトを宣言します。
    class ItemType{
      public string key;
      public int value;
    }

    private List<ItemType> myItem;

コンストラクタで newを呼び出し、myItemオブジェクトを作成します。
    public MyClass2()
    {
      myItem = new List<ItemType>();
    }

デフォルトプロパティの実装は下記コードです。
getでは myItemの要素でkeyメンバの文字列の値が、添え字に与えた名称と一致するものがあるか探し、最初に一致した要素の value メンバの値を結果として返します。 一致する要素が無ければ -1 を返します。
setでは、ItemType オブジェクトを作成し、添え字で与えられた文字列をkeyメンバに設定し、代入された値を value メンバに設定し、myItemオブジェクトに追加します。~
    public int this[string key_string]
    {
      get
      {
        foreach (ItemType t in myItem) {
          if (t.key == key_string) {
            return t.value;
          }
        }
        return -1;
      }
      set
      {
        ItemType it = new ItemType();
        it.key = key_string;
        it.value = value;
        myItem.Add(it);
      }
    }

呼び出し側のコードは下記です。MyClass2 オブジェクトを作成し、添え字に文字列を指定して代入をします。
参照時にはMyClass2オブジェクトに添え字を与えて値を取り出します。
Penguin のキーに 200、Duck のキーに30、Bearのキーに420 を代入しています。結果は Bear Duck Penguin Whale の順番で参照して表示しますので、 テキストボックスには 420, 30, 200, -1 の順番で数値の結果が表示されます。
    private void button2_Click(object sender, EventArgs e)
    {
      MyClass2 mc2 = new MyClass2();
      mc2["Penguin"] = 200;
      mc2["Duck"] = 30;
      mc2["Bear"] = 420;

      textBox1.Text += mc2["Bear"].ToString() + "\r\n";
      textBox1.Text += mc2["Duck"].ToString() + "\r\n";
      textBox1.Text += mc2["Penguin"].ToString() + "\r\n";
      textBox1.Text += mc2["Whale"].ToString() + "\r\n";
    }

実行結果

上記のプログラムのプロジェクトを実行します。下図のウィンドウが表示されます。


[button2]をクリックします。下図のメッセージがテキストボックスに表示されます。キーに対応付けられて数値が保存できていることが確認できます。 また、マッチしない場合は-1を返すロジックも正しく実行されました。

著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
掲載日: 2021-02-23
iPentec all rights reserverd.