Come posso sovraccaricare l'operatore parentesi quadra in C #?


254

DataGridView, ad esempio, ti consente di fare questo:

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

ma per la mia vita non riesco a trovare la documentazione sull'operatore indice / parentesi quadra. Come lo chiamano? Dove viene implementato? Può lanciare? Come posso fare la stessa cosa nelle mie lezioni?

ETA: grazie per tutte le risposte rapide. In breve: la relativa documentazione è sotto la proprietà "Articolo"; il modo di sovraccarico è dichiarando una proprietà simile public object this[int x, int y]{ get{...}; set{...} }; l'indicizzatore per DataGridView non viene lanciato, almeno in base alla documentazione. Non menziona cosa succede se si forniscono coordinate non valide.

Di nuovo ETA: OK, anche se la documentazione non ne fa menzione (la cattiva Microsoft!), Si scopre che l'indicizzatore per DataGridView in effetti lancerà un ArgumentOutOfRangeException se lo fornisci con coordinate non valide. Giusto avvertimento.

Risposte:


374

puoi trovare come farlo qui . In breve è:

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

Se hai solo bisogno di un getter, puoi utilizzare anche la sintassi nella risposta di seguito (a partire da C # 6).


9
un piccolo commento: a seconda di cosa stai facendo, potresti trovare più appropriato fare: get {return base [i]; } set {base [i] = valore; }
MikeBaz - MSFT,

7
Questo non è un sovraccarico dell'operatore. È indicizzatore
Destructor

5
Indicizzatore, potrebbe anche essere un operatore unario.
alan2here

1
Nel 2019, dovrebbe essere selezionata una nuova risposta, questa . Peccato che il SO non abbia una funzione per gestire le risposte deprecate, poiché il nuovo non è vicino per ottenere 350+ voti, anche se li merita.
minuti

@mins Ho incluso un link all'altra risposta.
Ruben,

41

Sarebbe la proprietà dell'oggetto: http://msdn.microsoft.com/en-us/library/0ebtbkkc.aspx

Forse qualcosa del genere funzionerebbe:

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

Molte grazie! Se potessi impostare due risposte, aggiungerei anche le tue - nessun altro sapeva cercare l'oggetto nella documentazione ...
Coderer

5
In termini di come viene implementato, è "Item", ma in termini di C # è "questo"
Marc Gravell

1
Giusto, ma ho chiesto "per la mia vita non riesco a trovare la documentazione sull'operatore indice / parentesi quadra" - intendevo quando cerchi una classe di libreria in MSDN, dove ti dicono dell'operatore? Ecco perché ho fatto l'ultimo "ETA" su ciò che genera: i documenti sono sbagliati .
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 delle informazioni

Per staffa:

public Object this[int index]
{

}

MA

L'operatore di indicizzazione dell'array non può essere sovraccaricato ; tuttavia, i tipi possono definire indicizzatori, proprietà che accettano uno o più parametri. I parametri dell'indicizzatore sono racchiusi tra parentesi quadre, proprio come gli indici dell'array, ma i parametri dell'indicizzatore possono essere dichiarati di qualsiasi tipo (a differenza degli indici dell'array, che devono essere integrali).

Da MSDN


sì, può essere sovraccaricato, purché la firma del parametro sia diversa, esattamente come le restrizioni di sovraccarico di qualsiasi altro metodo
Charles Bretana,

Può, ma non per la condizione che ho scritto. Viene da MSDN. Controlla la fonte se non mi credi
Patrick Desjardins,

1
Scusa se ho letto male il tuo post, ma a che condizioni ti riferisci?
Charles Bretana,

+1 per l'elenco pratico. Cordiali saluti il ​​collegamento è morto. (4 anni dopo, lo so)
Mixxiphoid

Vorrei aggiungere che ora puoi sovrascrivere sia il cast implicito che quello esplicito in C #.
Felype,

9

Se si utilizza C # 6 o versioni successive, è possibile utilizzare la sintassi basata sull'espressione per l'indicizzatore get-only:

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


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

5
In realtà, questo è davvero pericoloso - ora hai due implementazioni concorrenti: chiunque abbia una variabile digitata come Elenco <T> o IList <T> o IList ecc. Non eseguirà il tuo codice personalizzato.
Marc Gravell

1
D'accordo - se non altro, non è necessario derivare il tuo CustomCollection dall'elenco, ma non mi ero reso conto che fosse effettivamente pericoloso
Coderer,

Eseguirà comunque il codice personalizzato, no? Non importa quale tipo di variabile dichiari: è il tipo di oggetto che conta.
IZB

1
Ricordo amichevole del polimorfismo C #: ciò accade perché la classe base non dichiara la sua implementazione come virtuale. Se fosse dichiarato virtuale, il codice personalizzato verrebbe chiamato in ogni caso.
Almulo,

1
Inoltre, questo codice ti darà un avviso del compilatore poiché entrambi gli indicizzatori non sono virtuali. Il compilatore ti suggerirà di qualificare il tuo indicizzatore personalizzato con la newparola chiave.
tra

4

Per CLI C ++ (compilato con / clr) vedere questo collegamento MSDN .

In breve, a una proprietà può essere assegnato il nome "predefinito":

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

2

Ecco un esempio che restituisce un valore da un oggetto List interno. Dovresti darti l'idea.

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

1

Se intendi l'indicizzatore di array, puoi sovraccaricarlo semplicemente scrivendo una proprietà dell'indicizzatore. E puoi sovraccaricare, (scrivi quante ne vuoi) le proprietà dell'indicizzatore purché ognuna abbia una diversa firma del parametro

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
Per prima cosa intendi questo [], non questo () - tuttavia, fornire un personalizzato (ma diverso) questo [int] su qualcosa che è un elenco (IList / IList <T> / List <T>) è piuttosto pericoloso - e potrebbe portare a bug sottili tra le versioni "int index" e "int employeeId". Entrambi sono ancora richiamabili.
Marc Gravell

e in effetti, non credo che il codice che ho inserito sopra si compili senza aggiungere un'istruzione nuova o ignora proprio a causa dell'esistenza dell'implementazione di List <T> di questo [int]. Hai ragione sul potenziale quando lo fai, lo intendi semplicemente come esempio di sovraccarico dell'indicizzatore.
Charles Bretana,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.