C#でインデクサーを操作する方法
C#プログラミング言語には、インデクサーのサポートが含まれています。これは、オブジェクトを配列として使用できるようにする機能です。インデクサーはスマート配列とも呼ばれ、プロパティの定義方法と同様に定義できます。MSDNは次のように述べています。「インデクサーを使用すると、クラスまたは構造体のインスタンスに配列と同じようにインデックスを付けることができます。インデクサーは、アクセサーがパラメーターを受け取ることを除いて、プロパティに似ています。」
インデクサーとプロパティには複数の点で類似点がありますが、それらの間には微妙な違いがあります。プロパティとは異なり、インデックスを使用してインデクサーにアクセスできます。名前を使用してプロパティにアクセスする必要があることに注意してください。また、インデクサーはクラスのインスタンスメンバーであるため、静的にすることはできません。静的プロパティと非静的プロパティの両方を持つことができます。
次のコードスニペットは、インデクサーがどのように宣言されるかを示しています。
this [argument list]
{
get
{
}
Set
{
}
}
インデクサーの構文宣言に示されている修飾子は、private、public、protected、またはinternalである可能性があることに注意してください。
次のクラスについて考えてみます。
public class Contact
{
private string[] address = new string[3];
public string this[int index]
{
get
{
return address[index];
}
set
{
address[index] = value;
}
}
}
Contactクラスには、addressという名前のプライベートメンバーが含まれ、インデクサーを定義します。アドレスメンバーは、文字列型の配列です。Contactクラスのインスタンスを作成し、インデクサーを使用する方法は次のとおりです。
Contact contact = new Contact();
contact[0] = "Begumpet";
contact[1] = "Hyderabad";
contact[2] = "Telengana";
for (int i = 0; i < 3; i++)
Console.WriteLine (contact[i]);
インデクサーを定義するには、「this」キーワードを使用する必要があることに注意してください。インデクサーにアクセスするためのインデックスとして整数のみを使用することに制約されないことに注意してください。他のルックアップメカニズムを使用することもできます。インデクサーは通常、クラスがコレクションまたはオブジェクトを表す場合に使用されます。その後、インデクサーを使用して、インデックスを使用して特定の要素にアクセスできます。
例を見てみましょう。Customerという名前の次のクラスについて考えてみます。
public class Customer
{
public List Orders
{
get; set;
}
public Order this[int orderID]
{
get
{
return (from o in Orders
where o.OrderID == orderID
select o).First();
}
}
}
Customerクラスは、Orderタイプのインデクサーを定義します。また、Orderタイプのリストであるパブリックプロパティも含まれています。参考までに、Orderクラスを次に示します。
public class Order
{
public int OrderID
{
get; set;
}
}
次のコードスニペットは、Customerクラスのインデクサーにアクセスして特定の注文を取得する方法を示しています。
List lstOrder = new List();
Order o1 = new Order();
o1.OrderID = 1;
Order o2 = new Order();
o2.OrderID = 2;
lstOrder.Add(o1);
lstOrder.Add(o2);
Customer customer = new Customer();
customer.Orders = lstOrder;
Order o = customer[1];
上記のコードスニペットを参照してください。Orderタイプの汎用リストが作成され、CustomerクラスのインスタンスのOrdersプロパティに割り当てられていることに注意してください。次に、特定の注文インスタンスを取得するためのパラメータとしてOrderIdを渡すだけです。
インデクサーは継承をサポートし、ポリモーフィックにすることも、抽象化することもできます。仮想のインデクサーを定義する次のクラスについて考えてみます。ContactBaseクラスは、この記事の前半で説明したContactクラスの修正バージョンです。
public class ContactBase
{
protected string[] address = new string[3];
public virtual string this[int index]
{
get
{
return address[index];
}
set
{
address[index] = value;
}
}
}
これで、ContactBaseクラスからクラスを派生させ、以下に示すようにインデクサーをオーバーライドできます。
public class ConcreteContact: ContactBase
{
public override string this[int index]
{
get
{
return address[index];
}
set
{
address[index] = value;
}
}
}
そのため、上記のコード例では、型を継承しながらインデクサーを使用する方法と、インデクサーがポリモーフィックな動作を示す方法について説明しました。
インデクサーを抽象として定義することもできます。これを行うには、抽象クラスを作成してから、その中でインデクサーを抽象として定義する必要があります。ContactBaseクラスを変更し、インデクサーを抽象として定義しましょう。ContactBaseクラスの変更バージョンは次のようになります。
public abstract class ContactBase
{
protected string[] address = new string[3];
public abstract string this[int index]
{
get; set;
}
}
とにかくConcreteContactクラスを変更する必要はありません。以下に示すように、インデクサーを利用して、ConcreteContactクラスのインスタンスに文字列値を割り当てることができます。
ConcreteContact contact = new ConcreteContact();
contact[0] = "Begumpet";
contact[1] = "Hyderabad";
contact[2] = "Telengana";