C#で角かっこ演算子をオーバーロードするにはどうすればよいですか?


254

たとえば、DataGridViewを使用すると、次のことができます。

DataGridView dgv = ...;
DataGridViewCell cell = dgv[1,5];

しかし、私の人生では、index / square-bracket演算子に関するドキュメントを見つけることができません。彼らはそれを何と呼びますか?どこに実装されていますか?投げられますか?自分のクラスで同じことをするにはどうすればよいですか?

ETA:迅速な回答をありがとうございます。簡単に言うと、関連するドキュメントは "Item"プロパティの下にあります。オーバーロードする方法は、次のようなプロパティを宣言することですpublic object this[int x, int y]{ get{...}; set{...} }。少なくともドキュメントによると、DataGridViewのインデクサーはスローしません。無効な座標を指定するとどうなるかについては触れられていません。

ETA再度:OK、ドキュメントでは言及されていません(いたずらなMicrosoft!)が、無効な座標を指定すると、DataGridViewのインデクサーが実際にArgumentOutOfRangeExceptionをスローすることがわかります。公正警告。

回答:


374

ここでそれを行う方法を見つけることができます。要するに、それは:

public object this[int i]
{
    get { return InnerList[i]; }
    set { InnerList[i] = value; }
}

ゲッターのみが必要な場合は、以下の回答の構文も使用できます(C#6以降)。


9
マイナーなコメント:何をしているのかによっては、次のようにする方が適切な場合があります。get {return base [i]; } set {base [i] = value; }
MikeBaz-MSFT 2012年

7
これは演算子のオーバーロードではありません。それはインデクサーです
デストラクタ

5
インデクサーは、単項演算子の場合もあります。
alan2here

1
2019年には、新しい回答、これを選択する必要があります。残念ながら、新しいSOは350以上の賛成票を得るにはほど遠いため、非推奨の回答を処理する機能はありませんが、それに値するものです。

@mins他の回答へのリンクを含めました。
ルーベン

41

それはアイテムのプロパティになります:http : //msdn.microsoft.com/en-us/library/0ebtbkkc.aspx

多分このようなものがうまくいくでしょう:

public T Item[int index, int y]
{ 
    //Then do whatever you need to return/set here.
    get; set; 
}

どうもありがとう!2つの答えを設定できたら、あなたの答えも追加します-ドキュメントでアイテムを探すことを他の誰も知りません
でした

5
それがどのように実装されるかという点では「アイテム」ですが、C#の用語では「これ」です
マークグラベル

1
そうですが、「私は一生、index / square-bracket演算子に関するドキュメントを見つけることができません」と尋ねました。MSDNでライブラリクラスを検索すると、演算子についてどこで説明されますか?それが私がスローするものについて最後の「ETA」を作成した理由です-ドキュメントは間違っています。
Coderer 2008年

26
Operators                           Overloadability

+, -, *, /, %, &, |, <<, >>         All C# binary operators can be overloaded.

+, -, !,  ~, ++, --, true, false    All C# unary operators can be overloaded.

==, !=, <, >, <= , >=               All relational operators can be overloaded, 
                                    but only as pairs.

&&, ||                  They can't be overloaded

() (Conversion operator)        They can't be overloaded

+=, -=, *=, /=, %=                  These compound assignment operators can be 
                                    overloaded. But in C#, these operators are
                                    automatically overloaded when the respective
                                    binary operator is overloaded.

=, . , ?:, ->, new, is, as, sizeof  These operators can't be overloaded

    [ ]                             Can be overloaded but not always!

情報源

ブラケットの場合:

public Object this[int index]
{

}

だが

配列のインデックス付け演算子はオーバーロードできません。ただし、タイプはインデクサー、1つ以上のパラメーターを受け取るプロパティを定義できます。インデクサーパラメーターは、配列インデックスと同様に角かっこで囲まれますが、インデクサーパラメーターは任意の型であると宣言できます(配列インデックスは整数である必要があります)。

MSDNから


はい、パラメータシグネチャが異なる限り、他のメソッドのオーバーロード制限とまったく同じように、オーバーロードできます
Charles Bretana

それはできますが、私が書いた状態ではできません。MSDNからです。私を信じていない場合はソースを確認してください
Patrick Desjardins

1
投稿を読み間違えた場合は申し訳ありませんが、どのような条件を参照していますか?
Charles Bretana、2008年

便利なリストの+1。参考までに、リンクが停止しました。(4年後、知っています)
Mixxiphoid 2013年

ここで、C#で暗黙的および明示的な型キャストの両方をオーバーライドできることを付け加えておきます。
フェリーペ2017

9

C#6以降を使用している場合は、get-onlyインデクサーに式本体の構文を使用できます。

public object this[int i] => this.InnerList[i];


6
public class CustomCollection : List<Object>
{
    public Object this[int index]
    {
        // ...
    }
}

5
実際、これは本当に危険です。競合する実装が2つあります。List<T>またはIList <T>またはIListなどの型の変数を持つユーザーは、カスタムコードを実行しません。
マークグラベル

1
同意します-他に何もなければ、リストからCustomCollectionを派生させる必要はありませんが、それが実際に危険であることに気付いていませんでした
Coderer

それでもカスタムコードは実行されますよね。どの変数型を宣言するかは関係ありません-重要なのはオブジェクトの型です。
izb

1
C#ポリモーフィズムのわかりやすいメモ:これは、基本クラスがその実装を仮想として宣言していないために発生します。仮想として宣言されている場合、カスタムコードはすべてのケースで呼び出されます。
almulo、2015年

1
また、このコードは、両方のインデクサーが非仮想であるため、コンパイラ警告を表示します。コンパイラは、カスタムインデクサーをnewキーワードで修飾することを提案します。
-amoss

4

CLI C ++(/ clrでコンパイル)については、このMSDNリンクを参照してください

つまり、プロパティに「デフォルト」という名前を付けることができます。

ref class Class
{
 public:
  property System::String^ default[int i]
  {
    System::String^ get(int i) { return "hello world"; }
  }
};

2

以下は、内部のListオブジェクトから値を返す例です。あなたにアイデアを与えるべきです。

  public object this[int index]
  {
     get { return ( List[index] ); }
     set { List[index] = value; }
  }

1

配列インデクサーを意味する場合は、インデクサープロパティを記述するだけでオーバーロードできます。そして、インデクサープロパティがそれぞれ異なるパラメーターシグネチャを持っている限り、インデクサープロパティをオーバーロードできます(必要な数だけ書き込む)

public class EmployeeCollection: List<Employee>
{
    public Employee this[int employeeId]
    {   
        get 
        { 
            foreach(var emp in this)
            {
                if (emp.EmployeeId == employeeId)
                    return emp;
            }

            return null;
        }
    }

    public Employee this[string employeeName]
    {   
        get 
        { 
            foreach(var emp in this)
            {
                if (emp.Name == employeeName)
                    return emp;
            }

            return null;
        }
    }
}

2
最初に、this()ではなくthis []を意味します。ただし、リスト(IList / IList <T> / List <T>)にカスタム(ただし異なる)this [int]を提供することは非常に危険です。 「int index」バージョンと「int employeeId」バージョンの間の微妙なバグにつながる可能性があります。どちらもまだ呼び出し可能です。
マークグラベル

実際、私が上記で入力したコードは、この[int]のList <T>実装が存在するため、新しいステートメントやオーバーライドステートメントを追加せずにコンパイルできるとは思いません。これを行うときの可能性については、あなたは正しいです。単に、インデクサーをオーバーロードする例としてそれを意味しました。
Charles Bretana、2008年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.