インデクサーの使用 (C# プログラミング ガイド)Using indexers (C# Programming Guide)

インデクサーは構文を簡略化します。これを使用すると、クラス構造体、またはインターフェイスを作成でき、クライアント アプリケーションは配列と同じようにアクセスできます。Indexers are a syntactic convenience that enable you to create a class, struct, or interface that client applications can access just as an array. インデクサーは、内部コレクションまたは配列をカプセル化することが主な目的である型で最も多く実装されます。Indexers are most frequently implemented in types whose primary purpose is to encapsulate an internal collection or array. たとえば、24 時間のうちの異なる 10 回の時刻で記録した温度を華氏で表す TempRecord クラスがあるとします。For example, suppose you have a class TempRecord that represents the temperature in Fahrenheit as recorded at 10 different times during a 24 hour period. このクラスには、温度値を格納する float[] 型の配列 temps が含まれています。The class contains an array temps of type float[] to store the temperature values. このクラスにインデクサーを実装することで、クライアントは、float temp = tr.temps[4] ではなく float temp = tr[4] として TempRecord インスタンスの温度にアクセスできます。By implementing an indexer in this class, clients can access the temperatures in a TempRecord instance as float temp = tr[4] instead of as float temp = tr.temps[4]. インデクサーはクライアント アプリケーションの構文を簡略化するだけでなく、クラスとその目的を、他の開発者たちにとってわかりやすい、より直感的なものにします。The indexer notation not only simplifies the syntax for client applications; it also makes the class and its purpose more intuitive for other developers to understand.

クラスまたは構造体でインデクサーを宣言するには、次の例のように this キーワードを使用します。To declare an indexer on a class or struct, use the this keyword, as the following example shows:

public int this[int index]    // Indexer declaration  
{  
    // get and set accessors  
}  

解説Remarks

インデクサーの型とそのパラメーターの型は、少なくとも、インデクサー自体と同程度にアクセス可能である必要があります。The type of an indexer and the type of its parameters must be at least as accessible as the indexer itself. アクセシビリティ レベルの詳細については、「アクセス修飾子 (C# リファレンス)」を参照してください。For more information about accessibility levels, see Access Modifiers.

インターフェイスでインデクサーを使用する方法の詳細については、「インターフェイスのインデクサー (C# プログラミング ガイド)」を参照してください。For more information about how to use indexers with an interface, see Interface Indexers.

インデクサーのシグネチャは、その仮パラメーターの数と型で構成されます。The signature of an indexer consists of the number and types of its formal parameters. これには、インデクサーの型や仮パラメーターの名前は含まれません。It doesn't include the indexer type or the names of the formal parameters. 同じクラス内に複数のインデクサーを宣言する場合は、異なるシグネチャが必要です。If you declare more than one indexer in the same class, they must have different signatures.

インデクサーの値は変数として分類されないため、インデクサーの値を refout パラメーターとして渡すことはできません。An indexer value is not classified as a variable; therefore, you cannot pass an indexer value as a ref or out parameter.

他の言語が使用できる名前をインデクサーに指定するには、次の例のように System.Runtime.CompilerServices.IndexerNameAttribute を使用します。To provide the indexer with a name that other languages can use, use System.Runtime.CompilerServices.IndexerNameAttribute, as the following example shows:

[System.Runtime.CompilerServices.IndexerName("TheItem")]  
public int this[int index]   // Indexer declaration  
{
    // get and set accessors  
}  

このインデクサーの名前は TheItem になります。This indexer will have the name TheItem. name 属性を指定しないと、Item が既定の名前になります。Not providing the name attribute would make Item the default name.

例 1Example 1

次の例は、プライベートな配列フィールド temps とインデクサーの宣言方法を示しています。The following example shows how to declare a private array field, temps, and an indexer. インデクサーを使用すれば、インスタンス tempRecord[i] に直接アクセスできます。The indexer enables direct access to the instance tempRecord[i]. インデクサーを使用しない場合は、配列を public メンバーとして宣言し、そのメンバー tempRecord.temps[i] に直接アクセスします。The alternative to using the indexer is to declare the array as a public member and access its members, tempRecord.temps[i], directly.

Console.Write ステートメントなどでインデクサーのアクセスが評価されると、get アクセサーが呼び出されることに注意してください。Notice that when an indexer's access is evaluated, for example, in a Console.Write statement, the get accessor is invoked. したがって、get アクセサーが存在しない場合は、コンパイル時エラーが発生します。Therefore, if no get accessor exists, a compile-time error occurs.

class TempRecord
{
    // Array of temperature values
    private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F, 
                                            61.3F, 65.9F, 62.1F, 59.2F, 57.5F };

    // To enable client code to validate input 
    // when accessing your indexer.
    public int Length
    {
        get { return temps.Length; }
    }
    // Indexer declaration.
    // If index is out of range, the temps array will throw the exception.
    public float this[int index]
    {
        get
        {
            return temps[index];
        }

        set
        {
            temps[index] = value;
        }
    }
}

class MainClass
{
    static void Main()
    {
        TempRecord tempRecord = new TempRecord();
        // Use the indexer's set accessor
        tempRecord[3] = 58.3F;
        tempRecord[5] = 60.1F;

        // Use the indexer's get accessor
        for (int i = 0; i < 10; i++)
        {
            System.Console.WriteLine("Element #{0} = {1}", i, tempRecord[i]);
        }

        // Keep the console window open in debug mode.
        System.Console.WriteLine("Press any key to exit.");
        System.Console.ReadKey();

    }
}
/* Output:
        Element #0 = 56.2
        Element #1 = 56.7
        Element #2 = 56.5
        Element #3 = 58.3
        Element #4 = 58.8
        Element #5 = 60.1
        Element #6 = 65.9
        Element #7 = 62.1
        Element #8 = 59.2
        Element #9 = 57.5
    */

他の値を使用したインデックス作成Indexing using other values

C# では、インデクサー パラメーター型は整数に制限されません。C# doesn't limit the indexer parameter type to integer. たとえば、文字列をインデクサーで使用すると有効な場合があります。For example, it may be useful to use a string with an indexer. このようなインデクサーは、コレクション内の文字列を検索し、適切な値を返すことによって実装される場合があります。Such an indexer might be implemented by searching for the string in the collection, and returning the appropriate value. アクセサーはオーバーロードできるため、文字列と整数のバージョンは共存できます。As accessors can be overloaded, the string and integer versions can co-exist.

例 2Example 2

次の例では、曜日を格納するクラスを宣言しています。The following example declares a class that stores the days of the week. get アクセサーは、曜日を示す文字列を受け取り、対応する整数を返します。A get accessor takes a string, the name of a day, and returns the corresponding integer. たとえば、"Sunday" は 0、"Monday" は 1 などと値を返します。For example, "Sunday" returns 0, "Monday" returns 1, and so on.

// Using a string as an indexer value
class DayCollection
{
    string[] days = { "Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat" };

    // This method finds the day or returns an Exception if the day is not found
    private int GetDay(string testDay)
    {

        for (int j = 0; j < days.Length; j++)
        {
            if (days[j] == testDay)
            {
                return j;
            }
        }

        throw new System.ArgumentOutOfRangeException(testDay, "testDay must be in the form \"Sun\", \"Mon\", etc");
    }

    // The get accessor returns an integer for a given string
    public int this[string day]
    {
        get
        {
            return (GetDay(day));
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        DayCollection week = new DayCollection();
        System.Console.WriteLine(week["Fri"]);

        // Raises ArgumentOutOfRangeException
        System.Console.WriteLine(week["Made-up Day"]);

        // Keep the console window open in debug mode.
        System.Console.WriteLine("Press any key to exit.");
        System.Console.ReadKey();
    }
}
// Output: 5

信頼性の高いプログラミングRobust programming

インデクサーのセキュリティと信頼性を改善するには、主に次の 2 つの方法があります。There are two main ways in which the security and reliability of indexers can be improved:

  • クライアント コードが無効なインデックス値を渡しても、それを処理できるように必ずエラー処理戦略を組み込んでください。Be sure to incorporate some type of error-handling strategy to handle the chance of client code passing in an invalid index value. このトピックの最初の例の TempRecord クラスには Length プロパティが用意されており、入力がインデクサーに渡される前にクライアント コードで検証できるようになっています。In the first example earlier in this topic, the TempRecord class provides a Length property that enables the client code to verify the input before passing it to the indexer. インデクサー自体にエラー処理コードを配置することもできます。You can also put the error handling code inside the indexer itself. インデクサーのアクセサー内部でスローされる例外はすべて、ユーザーのために文書化してください。Be sure to document for users any exceptions that you throw inside an indexer accessor.

  • get および set アクセサーのアクセシビリティを設定し、適切な制限を指定します。Set the accessibility of the get and set accessors to be as restrictive as is reasonable. これは、set アクセサーの場合、特に重要です。This is important for the set accessor in particular. 詳細については、「アクセサーのアクセシビリティの制限」を参照してください。For more information, see Restricting Accessor Accessibility.

関連項目See also