Почему новый индекс оператора шляпы из функции вырезания массива в C# 8 не начинается с 0?
В C# 8.0 представлен удобный способ нарезки массивов - см. Официальный пост C# 8.0.
Синтаксис для доступа к последнему элементу массива
int value[] = { 10, 11, 12, 13 };
int a = value[^1]; // 13
int b = value[^2]; // 12
Мне интересно, почему индексирование для доступа к элементам в обратном направлении начинается с 1 вместо 0? Есть ли техническая причина для этого?
1 ответ
Официальный ответ
Для большей наглядности вот комментарий от Мэдс Торгерсен, объясняющий это дизайнерское решение из блога C# 8:
Мы решили следовать Python, когда дело доходит до арифметики начала и конца.
0
обозначает первый элемент (как всегда) и^0
"length'th" элемент, то есть тот, который с самого конца. Таким образом, вы получите простое отношение, где позиция элемента от начала плюс его позиция от конца равна длине.x
в^x
это то, что вы вычли бы из длины, если бы вы сделали математику самостоятельно.Почему бы не использовать минус (
-
) вместо новой шляпы (^
) оператор? Это в первую очередь связано с диапазонами. Опять же, в соответствии с Python и большей частью отрасли, мы хотим, чтобы наши диапазоны были включающими в начале, исключительными в конце. Какой индекс вы передаете, чтобы сказать, что диапазон должен идти до конца? В C# ответ прост:x..^0
идет отx
к концу. В Python нет явного индекса, который вы можете дать:-0
не работает, потому что это равно0
, первый элемент! Так что в Python вы должны полностью отключить конечный индекс, чтобы выразить диапазон, идущий до конца:x..
, Если вычисляется конец диапазона, вам нужно помнить, чтобы иметь специальную логику на случай, если0
, Как вx..-y
, гдеy
был вычислен и вышел0
, Это распространенная неприятность и источник ошибок.Наконец, обратите внимание, что индексы и диапазоны являются первоклассными типами в.NET/C#. Их поведение не связано с тем, к чему они применяются, или даже для использования в индексаторе. Вы можете полностью определить свой собственный индексатор, который принимает индекс и другой, который принимает
Range
- и мы собираемся добавить такие индексаторы, например,Span
, Но вы также можете иметь методы, которые принимают диапазоны, например.
Мой ответ
Я думаю, что это соответствует классическому синтаксису, к которому мы привыкли:
value[^1] == value[value.Length - 1]
Если бы он использовал 0, было бы непонятно, когда два синтаксиса использовались бок о бок. Таким образом, у него снижается когнитивная нагрузка.
Другие языки, такие как Python, также используют то же соглашение.