インデクサのソースを表示
←
インデクサ
ナビゲーションに移動
検索に移動
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループに属する利用者のみが実行できます:
登録利用者
。
このページのソースの閲覧やコピーができます。
[[プログラミング言語]]における'''インデクサ''' ({{lang-en-short|indexer}}) は、[[クラス (コンピュータ)|クラス]]や[[構造体]]の[[インスタンス]]に[[配列]]と同様の添字を指定してアクセスするための構文である。 == 概要 == 言語仕様に配列を持つプログラミング言語の多くは、配列要素にアクセスするための添字による特殊な構文を持つ。例えば[[C言語]]から派生した言語では、添え字演算子<code><nowiki>[]</nowiki></code>により要素アクセスできる。以下は[[C Sharp|C#]]の例である。 <syntaxhighlight lang="csharp"> double[] array = new double[10]; for (int i = 0; i < array.Length; ++i) { array[i] = i * 0.1; } System.Console.WriteLine(array[5]); </syntaxhighlight> その一方で、例えば動的配列 (配列リスト) や辞書 ([[連想配列]]) などのように、(言語組み込みの)配列以外のデータ構造を持つコレクションオブジェクトの要素に対しても、配列のように添え字でアクセスできると便利かつ直感的である。 インデクサがない言語では通常getterやsetterと呼ばれる要素アクセスのためのメソッドを実装したり、内部の配列を[[プロパティ (プログラミング)|プロパティ]]として公開するなどしてアクセスするのが一般的であるが、以下の問題点がある。 * コードの冗長化による可読性や直感性の低下 * 言語によってはgetやsetが識別子として扱われている場合があり、アクセサメソッドの名前が冗長化しやすい <!--* getterメソッドの戻り値を使用しないような無駄なメソッド呼び出しが許容されてしまう--> * 内部配列(実装)を外部に公開するようなパターンは([[カプセル化]]の観点から)そもそも避けるべきである インデクサを用いることでオブジェクト内のコレクション要素へのアクセスを、配列へのアクセスと同様に記述できる。 <!--また、メソッド呼び出しと異なりインデクサへのアクセスはプロパティのそれと同様に扱われる。そのため、開発環境のサポートが受けられる場合において、配列要素にアクセスはするが戻り値の処理を記述し忘れる、などのコードは構文レベルでのエラーとなりコーディングミスを認識しやすくなる。--><!-- これは単に、メソッドの戻り値を無視すると警告を出すようなコードインスペクション機能を使えばよいだけ。インデクサの利点として挙げるべきではない。メソッドの戻り値を無視しても既定で警告を出さないような、Microsoft Visual Studioを基準・前提にした考えのみをここで記述するべきではない。 --> ただし、インデクサは実質的にはgetter/setterメソッド呼び出しの[[糖衣構文]]であり、インデクサそのものは当然ながら[[反復子]]としての機能は持たない。インデクサを記述したからといって配列のように[[foreach文]]などの反復構文がそのまま使えるわけではない<ref group="※">C#ではGetEnumeratorという名前のメソッドを実装することでforeach文が使えるようになる。</ref>他、メソッド呼び出しのオーバーヘッド減少などの効果も特にない(コンパイラによるインライン展開等は当然受けるが、インデクサ固有の利点ではない)。 [[C Sharp|プログラミング言語C#]]のインデクサは[[C++]]の添え字演算子の[[多重定義]]と似ているが、次のような点で発展したものだと見ることもできる。ただしC++とC#の言語設計上の事情も絡んでいるので、単純に比較できるものではない。 * インデクサでは[[プロパティ (プログラミング)|プロパティ]]のように値を得るときと代入するときとで実際には別のメソッドに分かれている。 * インデクサは単独で多次元な配列を模倣できる。C++で同じようなことをするには間に一時的にオブジェクトを入れるなどの技巧を凝らす必要がある{{要説明|date=2019年2月}}。 他の言語ではC#のインデクサに似た機能として、[[Microsoft Visual Basic .NET|Visual Basic .NET]]の引数付きプロパティや[[C++/CLI]]のインデックス付きプロパティなどが存在する。 インデクサをサポートしない言語、例えば[[Java]]において、配列リストを表す[[データ構造|コレクション]]の要素へのアクセスは、次のような<code>java.util.List</code><ref group="※">{{Javadoc:SE|name=java.util.List|java/util|List}}</ref>インターフェイスのget/set[[メソッド]]によって提供される。 <syntaxhighlight lang="java"> var list = new java.util.ArrayList<Integer>(java.util.Collections.nCopies(10, 0)); // index 番目の要素に値を設定。 // void set(int index, E element) list.set(2, 100); // index 番目の要素を取得。 // E get(int index) int val = list.get(2); </syntaxhighlight><!-- C#と簡単に比較できるようにするため、Java 10のvarを使用している。 --> 一方、C#のインデクサでは、配列リストの要素へのアクセスを配列のアクセスと同じように記述することができる。以下の例では<code>System.Collections.Generic.IList</code>インターフェイスで定義されているインデクサを使用している。 <syntaxhighlight lang="csharp"> var list = new System.Collections.Generic.List<int>(new int[10]); list[2] = 100; int val = list[2]; </syntaxhighlight> インデクサを定義する際、インデックスとして整数以外の値 (文字列やオブジェクトなど) も使用することができ、[[ハッシュテーブル]]などの[[連想配列]]を表すコレクションに使用されている。 <syntaxhighlight lang="csharp"> var map = new System.Collections.Generic.Dictionary<string, double>(); map["key1"] = 0.1; double val = map["key1"]; </syntaxhighlight> なお、[[連結リスト]]実装である<code>System.Collections.Generic.LinkedList</code>は、要素アクセスの計算量が <math>O(1)</math> ではなく <math>O(n)</math> であり、インデクサは提供されない。 == 例 == === C# === [[C Sharp|C#]]においては、クラスおよび構造体の内部にインデクサを持つことができる。 インデクサは<code>this[添え字リスト]</code>の形式で宣言する。 インデクサの構文内では<code>get</code>/<code>set</code>が、<code>set</code>アクセサ内では<code>value</code>がそれぞれ文脈キーワードとして機能する。 <syntaxhighlight lang="csharp"> class Matrix2x2 { private readonly int[][] items = new[]{ new[] { 0, 0 }, new[] { 0, 0 }, }; // セルの値を取得、設定するインデクサ。 public int this[int index0, int index1] { get { return items[index0][index1]; } set { items[index0][index1] = value; } } } </syntaxhighlight> 呼び出し側では、配列にアクセスするような構文でインデクサの機能を呼び出す。 <syntaxhighlight lang="csharp"> var matrix = new Matrix2x2(); // setアクセス matrix[0, 0] = 10; // getアクセス int num = matrix[0, 1]; // get ⇒ 加算 ⇒ set matrix[1, 0] += 10; </syntaxhighlight> 通常のメソッドと異なり、代入を伴わないインデクサメソッドの呼び出しは行えない。下記のような呼び出しは構文エラーとなる他、戻り値void型のインデクサを定義することもできない。ただし、インデクサを介して呼び出したオブジェクトのメンバを呼び出すような場合は構文上問題ない。 <syntaxhighlight lang="csharp"> // 構文エラーとして扱われる。 matrix[1, 0]; // 次の呼び出しは問題ない(この例では意味をなさない呼び出しだが) matrix[1, 0].ToString(); </syntaxhighlight> ==== 他言語との相互運用 ==== 他言語との相互運用のため、既定では<code>Item</code>という名前のインデックス付きプロパティが自動生成される。 <code>System.Runtime.CompilerServices.IndexerNameAttribute</code>属性を付加することで、自動生成されるインデクサの名前を明示的に指定できる。 この機能が利用されている代表的な例として、<code>System.String</code>クラスが挙げられる。<code>System.String</code>クラスではインデクサの名前は<code>Chars</code>となるように指定されている。 <ref>[https://referencesource.microsoft.com/#mscorlib/system/string.cs,8307d03426b56fe1 string.cs]</ref> ==== スニペット ==== Visual Studio IDE や Visual Studio Code では、以下のようなコードスニペットが用意されている。 * <code>indexer</code> : get,setアクセサを持つ標準的なインデクサ === Visual Basic (.NET) === Visual Basic においては、<code>Default</code>キーワード付きのインデックス付きプロパティがインデクサとしてアクセス可能となる。 <syntaxhighlight lang="vbnet"> Public Class StringArray Private m_Item As String() = New String(10) {} ' Defaultが宣言されたインデックス付きプロパティはインデクサとしてアクセス可能 Default Public Property Item(index As Integer) As String Get Return m_Item(index) End Get Set(ByVal value As String) m_Item(index) = value End Set End Property End Class </syntaxhighlight> <syntaxhighlight lang="vbnet"> Dim obj As StringArray = New StringArray ' getアクセス Dim str As String = obj(1) ' setアクセス obj(2) = str </syntaxhighlight> == 注釈 == {{Reflist|group="※"}} == 出典 == {{Reflist}} == 関連項目 == * [[オブジェクト指向プログラミング]] * [[カプセル化]] * [[プロパティ (プログラミング)|プロパティ]] * [[利用者定義演算子]] {{DEFAULTSORT:いんてくさ}} [[Category:プログラミング言語の構文]] [[Category:プログラミング言語のトピック]] {{Computer-stub}}
このページで使用されているテンプレート:
テンプレート:Computer-stub
(
ソースを閲覧
)
テンプレート:Lang-en-short
(
ソースを閲覧
)
テンプレート:Reflist
(
ソースを閲覧
)
テンプレート:要説明
(
ソースを閲覧
)
インデクサ
に戻る。
ナビゲーション メニュー
個人用ツール
ログイン
名前空間
ページ
議論
日本語
表示
閲覧
ソースを閲覧
履歴表示
その他
検索
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
特別ページ
ツール
リンク元
関連ページの更新状況
ページ情報