C # 8.0 présente un moyen pratique de découper les tableaux - voir blogpost officiel C # 8. .
La syntaxe pour accéder au dernier élément d'un tableau est
int value[] = { 10, 11, 12, 13 };
int a = value[^1]; // 13
int b = value[^2]; // 12
Je me demande pourquoi l'indexation pour accéder aux éléments en arrière commence à 1 au lieu de 0? Y a-t-il une raison technique à cela?
Pour une meilleure visibilité, voici un commentaire de Mads Torgersen expliquant cette décision de conception dans le article de blog C # 8 :
Nous avons décidé de suivre Python en ce qui concerne l'arithmétique de début et de fin.
0
Désigne le premier élément (comme toujours), et^0
L'élément "length’th", c'est-à-dire celui qui se trouve juste à la fin. De cette façon, vous obtenez une relation simple, où la position d'un élément depuis le début plus sa position depuis la fin est égale à la longueur. lex
dans^x
Est ce que vous auriez soustrait de la longueur si vous aviez fait le calcul vous-même.Pourquoi ne pas utiliser le signe moins (
-
) au lieu du nouveau chapeau (^
) opérateur? Cela concerne principalement les plages. Toujours en accord avec Python et la plupart de l'industrie, nous voulons que nos plages soient inclusives au début, exclusives à la fin. Quel est l'indice que vous passez pour dire qu'une plage devrait aller tout le chemin vers la fin? En C # la réponse est simple:x..^0
va dex
à la fin. En Python, il n'y a pas d'index explicite que vous pouvez donner:-0
ne fonctionne pas, car il est égal à0
, le premier élément! Donc, en Python, vous devez laisser complètement l'index de fin pour exprimer une plage qui va à la fin:x..
. Si la fin de la plage est calculée, alors vous devez vous rappeler d'avoir une logique spéciale au cas où elle sortirait à0
. Un péchéx..-y
, oùy
a été calculé et est sorti vers0
. C'est une nuisance courante et une source de bugs.Enfin, notez que les indices et les plages sont des types de première classe en .NET/C #. Leur comportement n'est pas lié à ce à quoi ils sont appliqués, ni même à être utilisé dans un indexeur. Vous pouvez définir totalement votre propre indexeur qui prend Index et un autre qui prend
Range
- et nous allons ajouter de tels indexeurs par exempleSpan
. Mais vous pouvez également avoir des méthodes qui prennent des plages, par exemple.
Je pense que cela correspond à la syntaxe classique à laquelle nous sommes habitués:
value[^1] == value[value.Length - 1]
S'il utilisait 0, ce serait déroutant lorsque les deux syntaxes étaient utilisées côte à côte. De cette façon, il a une charge cognitive inférieure.
D'autres langages comme Python utilisent également la même convention.