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
.