Pourquoi le nouvel index d'opérateur de chapeau de la fonctionnalité de découpage de tableau C # 8 ne commence-t-il pas à 0?

156

C # 8.0 présente un moyen pratique de découper des tableaux - voir le blog officiel de C # 8.0 .

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 à l'envers commence à 1 au lieu de 0? Y a-t-il une raison technique à cela?

Michael Pittino
la source
11
Notez que les plages C ++ le sont également [beginInclusive, endExclusive). C'est une convention commune.
bommelding
3
@Sinatr: Sur la base de ce billet de blog, la syntaxe pour tout renvoyer serait value[0..^0], puisque l'index de fin est exclusif (c'est ainsi que fonctionnent la plupart des autres langues). Aussi, commodément, value[^i..^0]vous donnera les derniers iéléments.
BlueRaja - Danny Pflughoeft
1
@bommelding: C ++ est rbegin()quelque peu en désaccord avec cette notion - le premier élément de cette plage n'est pas non plus celui au-delà de la fin. ;-)
DevSolar
1
Oh cool, cela ressemble à l'équivalent de l'indexation négative en python:value[-1] # 13
cs95
1
@coldspeed Et en Ruby la même chose que Python. Je suppose qu'ils ont tous deux emprunté cette convention à Perl.
Wayne Conrad

Réponses:

170

Réponse officielle

Pour une meilleure visibilité, voici un commentaire de Mads Torgersen expliquant cette décision de conception tirée du billet de blog C # 8 :

Nous avons décidé de suivre Python en ce qui concerne l'arithmétique du début et de la fin. 0 désigne le premier élément (comme toujours) et  ^0 l'élément «length'th», c'est-à-dire celui 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. le  x in  ^x est ce que vous auriez soustrait de la longueur si vous aviez fait le calcul vous-même.

Pourquoi ne pas utiliser le minus ( -) au lieu du nouvel ^opérateur hat ( )? Cela concerne principalement les plages. Encore une fois, conformément à Python et à la plupart de l'industrie, nous voulons que nos gammes soient inclusives au début, exclusives à la fin. Quel est l'index que vous transmettez pour dire qu'une plage doit aller jusqu'au bout? En C #, la réponse est simple: x..^0va de  x la fin. En Python, il n'y a pas d'index explicite que vous pouvez donner: -0ne fonctionne pas, car il est égal au 0premier élément! Donc , en Python, vous devez quitter l'indice final complètement d'exprimer une gamme qui va à la fin: x... Si la fin de la plage est calculée, vous devez vous rappeler d'avoir une logique spéciale au cas où elle en sortirait 0. Comme dans x..-y, oùya été calculé et est sorti 0. C'est une nuisance courante et une source de bugs.

Enfin, notez que les index et les plages sont des types de première classe dans .NET / C #. Leur comportement n'est pas lié à ce à quoi ils sont appliqués, ni même à être utilisés dans un indexeur. Vous pouvez totalement définir votre propre indexeur qui prend Index et un autre qui prend Range- et nous allons ajouter de tels indexeurs par exemple  Span. Mais vous pouvez également avoir des méthodes qui prennent des plages, par exemple.

Ma réponse

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, la charge cognitive est plus faible .

D'autres langages comme Python utilisent également la même convention.

Martin Zikmund
la source
13
Correction mineure au commentaire de Mads: vous n'avez pas à laisser complètement l'index de fin en python. Vous pouvez utiliser Noneà la place d'un numéro: [0,1,2,3,4][2:None] == [2,3,4]. Mais, oui, vous ne pouvez pas utiliser un entier comme index de fin (sans calculer la longueur évidemment).
Giacomo Alzetta
4
Attendez ... qu'est-ce qui ne va pas x..? Cela semble bien et je n'ai jamais eu de problème avec la [3:]syntaxe python .
mowwwalker
8
@mowwwalker - n'est-ce pas déjà couvert dans la citation? "Donc en Python ... 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"
Damien_The_Unbeliever
3
Le commentaire de @mowwwalker Mads concernait des cas dans lesquels vous ne savez pas quelle sera la valeur de l'index car elle est calculée d'une manière ou d'une autre. Ils disent que dans le cas où vous voulez calculer endIndexcomme un indice négatif (c'est-à-dire un index à partir de la fin), vous aurez une discontinuité entre les nombres négatifs et positifs car cela 0ne fonctionnera pas correctement dans ce cas. Comme je l'ai souligné, vous devez remplacer 0par Nonepour cela. Cela signifie que votre code doit ressembler à, seq[startIndex:endIndex or None]par exemple. Le or Nonedoit être omis si endIndexon s'attend à ce qu'il soit positif.
Giacomo Alzetta le
5
Il est bon de voir qu'ils ne répètent pas l'erreur de Python avec la chose -0. La gestion de ce cas spécial est un énorme problème et beaucoup trop facile à oublier.
user2357112 prend en charge Monica le