Délégués

Références

L'actualité

Librairie

L'information

Introduction

Les indexeurs permettent aux instances d'une classe ou d'un struct d'être indexés comme des tableaux. La valeur indexée peut être définie ou récupérée sans spécifier explicitement un membre de type ou d'instance. Les indexeurs s'apparentent aux propriétés à l'exception près que leurs accesseurs acceptent des paramètres.

L'exemple suivant définit une classe générique avec des méthodes d'accesseur get et set simples pour attribuer et récupérer des valeurs. La classe Program classe crée une instance de cette classe pour le stockage des chaînes.


Définitions de corps d'expression

Il est courant pour l'accesseur get ou set d'un indexeur d'être constitué d'une instruction unique qui retourne ou définit une valeur. Les membres expression-bodied fournissent une syntaxe simplifiée pour prendre en charge ce scénario. à partir de C# 6, un indexeur en lecture seule peut être implémenté comme un membre expression-bodied, comme le montre l'exemple suivant.

Notez que => introduit le corps de l'expression et que le mot clé get n'est pas utilisé.

À partir de C# 7.0, l'accesseur get et l'accesseur set peuvent être implémentés en tant que membres expression-bodied. Dans ce cas, les deux mots clés get et set doivent être utilisés. Par exemple :

Vue d'ensemble des indexeurs

  • Les indexeurs permettent aux objets d'être indexés d'une manière similaire aux tableaux.
  • Un accesseur get retourne une valeur. Un accesseur set affecte une valeur.
  • Le mot clé this est utilisé pour définir l'indexeur.
  • Le mot clé value est utilisé pour définir la valeur affectée par l'indexeur set.
  • Les indexeurs n'ont pas besoin d'être indexés par une valeur entière. Il vous appartient de choisir comment définir le mécanisme de recherche spécifique.
  • Les indexeurs peuvent être surchargés.
  • Les indexeurs peuvent avoir plusieurs paramètres formels, par exemple, quand vous accédez à un tableau à deux dimensions.

Utilisation d'indexeurs

Les indexeurs simplifient, d'un point de vue syntaxique, la création d'une classe, d'un struct ou d'une interface auxquels les applications clientes peuvent accéder exactement comme à un tableau. Le plus souvent, les indexeurs sont implémentés dans les types dont l'objectif premier est d'encapsuler une collection ou un tableau interne. Prenons l'exemple d'une classe TempRecord qui représente la température, en Farenheit, enregistrée à 10 moments différents sur une période de 24 heures. Elle contient un tableau temps de type float[] pour stocker les valeurs de température. En implémentant un indexeur dans cette classe, les clients peuvent accéder aux températures dans une instance TempRecord sous la forme float temp = tr[4] et non sous la forme float temp = tr.temps[4]. La notation d'indexeur simplifie non seulement la syntaxe pour les applications clientes, mais elle permet également aux autres développeurs de comprendre de façon plus intuitive l'objectif de la classe.

Pour déclarer un indexeur sur une classe ou un struct, utilisez le mot clé this, comme dans l'exemple suivant :


Notes

Le type d'un indexeur et le type de ses paramètres doivent être au moins aussi accessibles que l'indexeur lui-même.

La signature d'un indexeur est composée du nombre et des types de ses paramètres formels. Elle ne comporte ni le type de l'indexeur ni le nom des paramètres formels. Si vous déclarez plusieurs indexeurs dans la même classe, ils doivent avoir des signatures différentes.

Une valeur d'indexeur n'est pas classée comme variable ; vous ne pouvez donc pas la passer comme paramètre ref ou out.

Pour affecter à l'indexeur un nom exploitable dans d'autres langages, utilisez System.Runtime.CompilerServices.IndexerNameAttribute, comme dans l'exemple suivant :

Cet indexeur portera le nom TheItem. Si vous ne précisez pas le nom de l'attribut, Item est utilisé comme nom par défaut.

Exemple

L'exemple suivant montre comment déclarer un champ de tableau privé temps, et un indexeur. L'indexeur permet d'accéder directement à l'instance tempRecord[i]. Comme alternative à l'utilisation de l'indexeur, vous pouvez déclarer le tableau comme membre public et accéder directement à ses membres, tempRecord.temps[i].

Notez que quand l'accès à un indexeur est évalué, par exemple dans une instruction Console.Write, l'accesseur get est appelé. C'est pourquoi une erreur de compilation se produit s'il n'existe aucun accesseur get.


Indexation avec d'autres valeurs

C# ne limite pas le type de paramètre d'indexeur au type entier. Par exemple, il peut être utile d'utiliser une chaîne avec un indexeur. Il est possible d'implémenter un tel indexeur en recherchant la chaîne dans la collection et en retournant la valeur appropriée. Comme les accesseurs peuvent être surchargés, les versions chaîne et entier peuvent coexister.

Exemple

L'exemple suivant déclare une classe qui stocke les jours de la semaine. Un accesseur get prend une chaîne, le nom d'un jour, et retourne l'entier correspondant. Par exemple, "Sunday" retourne 0, "Monday" retourne 1 et ainsi de suite.


Programmation fiable

La sécurité et la fiabilité des indexeurs peuvent être améliorées de deux manières principales :

  • N'oubliez pas d'incorporer une stratégie de gestion des erreurs au cas où le code client passerait une valeur d'index non valide. Dans le premier exemple décrit plus haut dans cette rubrique, la classe TempRecord fournit une propriété Length qui permet au code client de vérifier l'entrée avant de la passer à l'indexeur. Vous pouvez également placer le code de gestion des erreurs à l'intérieur de l'indexeur lui-même. N'oubliez pas d'indiquer aux utilisateurs toutes les exceptions que vous levez dans un accesseur d'indexeur.

  • Définissez pour les accesseurs get et set une accessibilité aussi restrictive que possible. Cela est particulièrement important dans le cas de l'accesseur set.

Indexeurs dans les interfaces

Des indexeurs peuvent être déclarés dans une interface. Les accesseurs d'indexeurs d'interface se distinguent sur plusieurs plans des accesseurs d'indexeurs de classe, à savoir :

  • Les accesseurs d'interface n'utilisent pas de modificateurs.
  • Un accesseur d'interface n'a pas de corps.

Par conséquent, un accesseur vise à indiquer si l'indexeur est en lecture-écriture, en lecture seule ou en écriture seule. L'exemple ci-dessous porte sur un accesseur d'indexeur d'interface :

La signature d'un indexeur doit se distinguer de tous les autres indexeurs déclarés dans la même interface.

Exemple

L'exemple suivant montre comment implémenter des indexeurs d'interface.

Dans l'exemple précédent, vous pouvez utiliser l'implémentation de membre d'interface explicite en utilisant le nom qualifié complet du membre d'interface. Par exemple :

Cependant, le nom qualifié complet est seulement nécessaire pour éviter toute ambiguïté quand la classe implémente plusieurs interfaces avec la même signature d'indexeur. Par exemple, si une classe Employee implémente deux interfaces, ICitizen et IEmployee, et que les deux interfaces ont la même signature d'indexeur, l'implémentation de membre d'interface explicite est nécessaire. Autrement dit, la déclaration d'indexeur suivante :

Implémente l'indexeur dans l'interface IEmployee, alors que la déclaration suivante :

implémente l'interface dans l'interface ICitizen.

Comparaison entre propriétés et indexeurs

Les indexeurs sont semblables aux propriétés. à l'exception des différences répertoriées dans le tableau suivant, toutes les règles définies pour les accesseurs des propriétés s'appliquent également aux accesseurs des indexeurs.

Property Indexeur
Permet aux méthodes d'être appelées comme si elles étaient des membres de données publics. Permet aux éléments d'une collection interne d'un objet d'être accessibles à l'aide de la notation de tableau sur l'objet lui-même.
Accessible par le biais d'un nom simple. Accessible par le biais d'un index.
Peut être un membre statique ou un membre d'instance. Doit être un membre d'instance.
Un accesseur get d'une propriété n'a aucun paramètre. Un accesseur get d'un indexeur possède la même liste de paramètres formels que l'indexeur.
Un accesseur set d'une propriété contient le paramètre value implicite. Un accesseur set d'un indexeur possède la même liste de paramètres formels que l'indexeur, outre le paramètre value.
Prend en charge la syntaxe abrégée avec les propriétés implémentées automatiquement. Ne prend pas en charge la syntaxe abrégée.