Como sobrecarregar o operador de colchete em C #?


254

O DataGridView, por exemplo, permite fazer isso:

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

mas, durante toda a minha vida, não consigo encontrar a documentação no operador de índice / colchete. Como eles chamam? Onde é implementado? Ele pode jogar? Como posso fazer a mesma coisa nas minhas próprias aulas?

ETA: Obrigado por todas as respostas rápidas. Resumidamente: a documentação relevante está na propriedade "Item"; a maneira de sobrecarregar é declarar uma propriedade como public object this[int x, int y]{ get{...}; set{...} }; o indexador para DataGridView não lança, pelo menos de acordo com a documentação. Ele não menciona o que acontece se você fornecer coordenadas inválidas.

ETA Novamente: OK, mesmo que a documentação não faça menção a isso (Microsoft impertinente!), Acontece que o indexador do DataGridView lançará de fato uma ArgumentOutOfRangeException se você fornecer coordenadas inválidas. Aviso justo.

Respostas:


374

você pode encontrar como fazer isso aqui . Em suma, é:

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

Se você precisar apenas de um getter, a sintaxe na resposta abaixo também poderá ser usada (a partir do C # 6).


9
um comentário menor: dependendo do que você está fazendo, você pode achar mais apropriado: get {return base [i]; } definir {base [i] = valor; }
MikeBaz - MSFT

7
Isso não está sobrecarregando o operador. É indexador
Destructor

5
Indexador, também pode ser um operador unário.
Alan2here 9/08

1
Em 2019, uma nova resposta deve ser selecionada, esta . Pena que o SO não tenha um recurso para lidar com respostas obsoletas, pois o novo não está perto de receber mais de 350 votos positivos, embora os mereça.
mins

@mins eu incluí um link para a outra resposta.
Ruben

41

Essa seria a propriedade do item: http://msdn.microsoft.com/en-us/library/0ebtbkkc.aspx

Talvez algo assim funcione:

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

Muito obrigado! Se eu pudesse definir duas respostas, eu gostaria de acrescentar o seu também - ninguém mais sabia que procurar item na documentação ...
Coderer

5
Em termos de como ele é implementado, é "Item", mas em C # termos, é "isto"
Marc Gravell

1
Certo, mas perguntei "por toda a minha vida, não consigo encontrar a documentação no operador de índice / colchete" - quis dizer quando você consulta uma classe de biblioteca no MSDN, onde eles falam sobre o operador? Foi por isso que fiz esse último "ETA" sobre o que ele lança - os documentos estão errados .
Coderer

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!

Fonte da informação

Para suporte:

public Object this[int index]
{

}

MAS

O operador de indexação da matriz não pode ser sobrecarregado ; no entanto, os tipos podem definir indexadores, propriedades que usam um ou mais parâmetros. Os parâmetros do indexador são colocados entre colchetes, assim como os índices da matriz, mas os parâmetros do indexador podem ser declarados como sendo de qualquer tipo (diferentemente dos índices da matriz, que devem ser integrais).

Do MSDN


sim, pode ser sobrecarregado, enquanto a assinatura parâmetro é diferente, exatamente como restrições sobrecarregar qualquer outro método
Charles Bretana

Pode, mas não para a condição que escrevi. É do MSDN. Verifique a fonte, se você não acredita em mim
Patrick Desjardins

1
Desculpe se eu li mal sua postagem, mas a que condição você está se referindo?
Charles Bretana 13/11/08

+1 para a lista útil. Para sua informação, o link morreu. (4 anos mais tarde, eu sei)
Mixxiphoid

Gostaria de acrescentar que você pode substituir a conversão de tipos implícita e explícita no C # agora.
Felype 15/09/17

9

Se você estiver usando o C # 6 ou posterior, poderá usar a sintaxe de expressão para o indexador de get-only:

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


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

5
Na verdade, isso é realmente perigoso - agora você tem duas implementações concorrentes: qualquer pessoa com uma variável digitada como List <T> ou IList <T> ou IList etc não executará seu código personalizado.
Marc Gravell

1
Concordou - se nada mais, não é necessário derivar a sua CustomCollection da lista, mas eu não tinha percebido que era realmente perigoso
Coderer

Ele ainda executará o código personalizado, não é? Não importa qual tipo de variável você declara - é o tipo de objeto que importa.
izb

1
Lembrete amigável do polimorfismo C #: isso acontece porque a classe base não declara sua implementação como virtual. Se fosse declarado como virtual, o código personalizado seria chamado em todos os casos.
Almulo 20/05

1
Além disso, esse código fornecerá um aviso do compilador, pois os dois indexadores não são virtuais. O compilador sugerirá que você qualifique seu indexador personalizado com a newpalavra - chave.
Amoss 18/05

4

Para CLI C ++ (compilado com / clr), consulte este link do MSDN .

Em resumo, uma propriedade pode receber o nome "padrão":

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

2

Aqui está um exemplo retornando um valor de um objeto interno da Lista. Deve lhe dar a idéia.

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

1

Se você quer dizer o indexador da matriz, você sobrecarrega isso apenas escrevendo uma propriedade do indexador. E você pode sobrecarregar (escrever quantas quiser) as propriedades do indexador, desde que cada uma tenha uma assinatura de parâmetro diferente

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
Primeiro, você quer dizer isso [], não isso () - no entanto, fornecer um costume (mas diferente) isso [int] em algo que é uma lista (IList / IList <T> / List <T>) é bastante perigoso - e pode levar a erros sutis entre as versões "int index" e "int employeeId". Ambos ainda são exigíveis.
Marc Gravell

e, de fato, não acho que o código digitado acima fosse compilado sem adicionar uma instrução nova ou de substituição precisamente devido à existência da implementação List <T> deste [int]. Você está certo sobre o potencial ao fazer isso, simplesmente o quis como exemplo de sobrecarga do indexador.
Charles Bretana 13/11/08
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.