Réponse officielle
Pour une meilleure visibilité, voici un commentaire de Mads Torgersen expliquant cette décision de conception depuis le Article de blog sur le 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
le "length'th" élément, 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 par rapport au début plus sa position par rapport à la fin est égale à la longueur. the x
sur ^x
est ce que vous auriez soustrait de la longueur si vous aviez fait le calcul vous-même.
Pourquoi ne pas utiliser le moins ( -
) au lieu du nouveau chapeau ( ^
) ? Cela concerne principalement les plages. Encore une fois, conformément à Python et à la plupart des entreprises, nous voulons que nos plages soient inclusives au début et exclusives à la fin. Quel est l'indice que vous passez pour dire qu'une plage doit aller jusqu'à la fin ? En C#, la réponse est simple : x..^0
va de x
jusqu'à la fin. En Python, il n'y a pas d'indice explicite que vous pouvez donner : -0
ne fonctionne pas, car il est égal à 0
le premier élément ! Ainsi, en Python, vous devez laisser l'indice de fin complètement absent pour exprimer une plage qui va jusqu'à la fin : x..
. Si la fin de l'intervalle est calculée, vous devez vous rappeler d'avoir une logique spéciale au cas où il s'agirait de 0
. Comme dans x..-y
, donde y
a été calculée et s'est avérée être 0
. C'est une nuisance courante et une source d'insectes.
Enfin, notez que les indices 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 à leur utilisation dans un indexeur. Vous pouvez tout à fait 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 aussi avoir des méthodes qui prennent des plages, par exemple.
Ma réponse
Je pense que c'est pour correspondre à la syntaxe classique à laquelle nous sommes habitués :
value[^1] == value[value.Length - 1]
S'il utilisait 0, il y aurait confusion lorsque les deux syntaxes sont utilisées côte à côte. De cette façon, il a inférieur la charge cognitive.
D'autres langages comme Python utilisent la même convention.
17 votes
Notez que les plages C++ sont également
[beginInclusive, endExclusive)
. C'est une convention courante.4 votes
@Sinatr : En se basant sur cet article de blog, la syntaxe pour tout renvoyer serait la suivante
value[0..^0]
puisque l'indice de terminaison est exclusif (c'est aussi le cas dans la plupart des autres langues). C'est également pratique,value[^i..^0]
vous donnera le dernieri
articles.2 votes
@bommelding : C++
rbegin()
n'est pas tout à fait d'accord avec cette idée : le premier élément de cette gamme n'est pas non plus celui qui va le plus loin ;-)2 votes
Oh cool, ça ressemble à l'équivalent de l'indexation négative en python :
value[-1] # 13
2 votes
@coldspeed Et en Ruby, c'est pareil qu'en Python. Je suppose qu'ils ont tous deux emprunté cette convention à Perl.
2 votes
Il semble contre-intuitif que
^1
signifie "le dernier élément" lorsqu'il est utilisé comme indice, et "l'avant-dernier élément" lorsqu'il est utilisé comme partie d'une plage.0 votes
@JoelMueller Dans une gamme,
^1
signifie la fin du (exclusif)Range
ou le dernier élément.