Comment surcharger l'opérateur entre crochets en C #?

254

DataGridView, par exemple, vous permet de faire ceci:

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

mais pour la vie de moi, je ne trouve pas la documentation sur l'opérateur d'index / crochet. Comment s'appellent-ils? Où est-il mis en œuvre? Peut-il lancer? Comment puis-je faire la même chose dans mes propres cours?

ETA: Merci pour toutes les réponses rapides. En bref: la documentation pertinente se trouve sous la propriété "Item"; la façon de surcharger est de déclarer une propriété comme public object this[int x, int y]{ get{...}; set{...} }; l'indexeur pour DataGridView ne lance pas, du moins selon la documentation. Il ne mentionne pas ce qui se passe si vous fournissez des coordonnées invalides.

ETA Encore une fois: OK, même si la documentation n'en fait pas mention (méchant Microsoft!), Il s'avère que l'indexeur pour DataGridView lèvera en fait une ArgumentOutOfRangeException si vous lui fournissez des coordonnées invalides. Avertissement juste.

Coderer
la source

Réponses:

374

vous pouvez trouver comment le faire ici . En bref, c'est:

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

Si vous n'avez besoin que d'un getter, la syntaxe de la réponse ci - dessous peut également être utilisée (à partir de C # 6).

Ruben
la source
9
un commentaire mineur: selon ce que vous faites, vous trouverez peut-être plus approprié de faire: get {return base [i]; } set {base [i] = valeur; }
MikeBaz - MSFT
7
Ce n'est pas une surcharge d'opérateur. Il est indexeur
Destructor
5
L'indexeur peut également être un opérateur unaire.
alan2here
1
En 2019, une nouvelle réponse devrait être sélectionnée, celle-ci . Dommage que SO n'ait pas de fonctionnalité pour traiter les réponses déconseillées, car la nouvelle n'est pas proche d'obtenir plus de 350 votes positifs, bien qu'elle les mérite.
min le
@mins J'ai inclus un lien vers l'autre réponse.
Ruben
41

Ce serait la propriété de l'élément: http://msdn.microsoft.com/en-us/library/0ebtbkkc.aspx

Peut-être que quelque chose comme ça fonctionnerait:

public T Item[int index, int y]
{ 
    //Then do whatever you need to return/set here.
    get; set; 
}
Ricardo Villamil
la source
Merci beaucoup! Si je pouvais définir deux réponses, j'ajouterais également la vôtre - personne d'autre ne savait chercher un élément dans la documentation ...
Coderer
5
En termes de mise en œuvre, c'est "Item", mais en C #, c'est "this"
Marc Gravell
1
D'accord, mais j'ai demandé "pour la vie de moi, je ne trouve pas la documentation sur l'opérateur d'index / crochet" - je voulais dire lorsque vous recherchez une classe de bibliothèque dans MSDN, où vous disent-ils sur l'opérateur? C'est pourquoi j'ai fait ce dernier "ETA" sur ce qu'il jette - les documents sont faux .
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!

Source d'information

Pour support:

public Object this[int index]
{

}

MAIS

L'opérateur d'indexation de tableau ne peut pas être surchargé ; cependant, les types peuvent définir des indexeurs, des propriétés qui prennent un ou plusieurs paramètres. Les paramètres d'indexeur sont placés entre crochets, tout comme les indices de tableau, mais les paramètres d'indexeur peuvent être déclarés de n'importe quel type (contrairement aux indices de tableau, qui doivent être intégrés).

Depuis MSDN

Patrick Desjardins
la source
oui, il peut être surchargé, tant que la signature du paramètre est différente, exactement comme toute autre restriction de surcharge d'une autre méthode
Charles Bretana
C'est possible, mais pas pour la condition que j'ai écrite. C'est de MSDN. Vérifiez la source si vous ne me croyez pas
Patrick Desjardins
1
Désolé si j'ai mal lu votre message, mais à quelle condition faites-vous référence?
Charles Bretana,
+1 pour la liste pratique. Pour info le lien est mort. (4 ans plus tard, je sais)
Mixxiphoid
Je voudrais ajouter que vous pouvez remplacer le cast de type implicite et explicite en C # maintenant.
Felype
9

Si vous utilisez C # 6 ou une version ultérieure, vous pouvez utiliser une syntaxe avec expression pour l'indexeur get-only:

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

amoss
la source
6
public class CustomCollection : List<Object>
{
    public Object this[int index]
    {
        // ...
    }
}
Jason Miesionczek
la source
5
En fait, c'est vraiment dangereux - vous avez maintenant deux implémentations concurrentes: toute personne avec une variable de type List <T> ou IList <T> ou IList etc. n'exécutera pas votre code personnalisé.
Marc Gravell
1
D'accord - si rien d'autre, il n'est pas nécessaire de dériver votre CustomCollection de la liste, mais je ne m'étais pas rendu compte que c'était réellement dangereux
Coderer
Il exécutera toujours le code personnalisé, n'est-ce pas? Peu importe le type de variable que vous déclarez - c'est le type d'objet qui compte.
izb
1
Rappel amical du polymorphisme C #: cela se produit car la classe de base ne déclare pas son implémentation virtuelle. S'il était déclaré virtuel, le code personnalisé serait appelé dans tous les cas.
almulo
1
En outre, ce code vous donnera un avertissement du compilateur car les deux indexeurs ne sont pas virtuels. Le compilateur vous proposera de qualifier votre indexeur personnalisé avec le newmot - clé.
Amoss
4

Pour CLI C ++ (compilé avec / clr), consultez ce lien MSDN .

En bref, une propriété peut être nommée "par défaut":

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

la source
2

Voici un exemple renvoyant une valeur à partir d'un objet List interne. Devrait vous donner l'idée.

  public object this[int index]
  {
     get { return ( List[index] ); }
     set { List[index] = value; }
  }
Rob Prouse
la source
1

Si vous voulez dire l'indexeur de tableaux, vous le surchargez simplement en écrivant une propriété d'indexeur.

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;
        }
    }
}
Charles Bretana
la source
2
Tout d'abord, vous voulez dire ceci [], pas ceci () - cependant, fournir un personnalisé (mais différent) ce [int] sur quelque chose qui est une liste (IList / IList <T> / List <T>) est assez dangereux - et pourrait conduire à des bugs subtils entre les versions "int index" et "int employeeId". Les deux sont toujours appelables.
Marc Gravell
et en fait, je ne pense pas que le code que j'ai entré ci-dessus se compilerait sans ajouter une nouvelle instruction ou une instruction override précisément en raison de l'existence de l'implémentation List <T> de ce [int]. Vous avez raison sur le potentiel lorsque vous faites cela, cela signifie simplement qu'il s'agit d'un exemple d'indexation de surcharge.
Charles Bretana