#### [SOLVED] Why doesn't the new hat-operator index from the C# 8 array-slicing feature start at 0?

C# 8.0 introduces a convenient way to slice arrays - see official C# 8.0 blogpost.

The syntax to access the last element of an array is

``````int value[] = { 10, 11, 12, 13 };

int a = value[^1]; // 13
int b = value[^2]; // 12
``````

I'm wondering why the indexing for accessing the elements backwards starts at 1 instead of 0? Is there a technical reason for this?

#### @Martin Zikmund 2019-01-08 13:07:59

For better visibility, here is a comment from Mads Torgersen explaining this design decision from the C# 8 blog post:

We decided to follow Python when it comes to the from-beginning and from-end arithmetic. `0` designates the first element (as always), and `^0` the “length’th” element, i.e. the one right off the end. That way you get a simple relationship, where an element's position from beginning plus its position from end equals the length. the `x` in `^x` is what you would have subtracted from the length if you’d done the math yourself.

Why not use the minus (`-`) instead of the new hat (`^`) operator? This primarily has to do with ranges. Again in keeping with Python and most of the industry, we want our ranges to be inclusive at the beginning, exclusive at the end. What is the index you pass to say that a range should go all the way to the end? In C# the answer is simple: `x..^0` goes from `x` to the end. In Python, there is no explicit index you can give: `-0` doesn’t work, because it is equal to `0`, the first element! So in Python, you have to leave the end index off completely to express a range that goes to the end: `x..`. If the end of the range is computed, then you need to remember to have special logic in case it comes out to `0`. As in `x..-y`, where `y` was computed and came out to `0`. This is a common nuisance and source of bugs.

Finally, note that indices and ranges are first class types in .NET/C#. Their behavior is not tied to what they are applied to, or even to be used in an indexer. You can totally define your own indexer that takes Index and another one that takes `Range` – and we’re going to add such indexers to e.g. `Span`. But you can also have methods that take ranges, for instance.

I think this is to match the classic syntax we are used to:

``````value[^1] == value[value.Length - 1]
``````

If it used 0, it would be confusing when the two syntaxes were used side-by-side. This way it has lower cognitive load.

Other languages like Python also use the same convention.

#### @Giacomo Alzetta 2019-01-08 17:01:43

Minor correction to Mads comment: you do not have to leave off the end index completely in python. You can use `None` in place of a number: `[0,1,2,3,4][2:None] == [2,3,4]`. But, yes you cannot use an integer as end index (without computing the length obviously).

#### @mowwwalker 2019-01-08 21:27:36

Wait.. what's wrong with `x..`? That seems fine and I've never had problem with the python `[3:]` syntax.

#### @Mariusz Pawelski 2019-01-09 00:22:00

@mowwwalker nothing wrong. I seems that `x..` syntax will be supported too. It's in example of ranges proposal

#### @Damien_The_Unbeliever 2019-01-09 08:26:12

@mowwwalker - isn't that already covered in the quote? "So in Python ... If the end of the range is computed, then you need to remember to have special logic in case it comes out to 0"

#### @Giacomo Alzetta 2019-01-09 13:18:13

@mowwwalker Mads comment was about cases in which you do not know what the index value is going to be because it's computed in some way. They are saying that in the case you want to compute `endIndex` as a negative index (i.e. index from the end) you will have a discontinuity between negative and positive numbers because `0` isn't going to work in the correct way in that case. As I pointed out you have to replace `0` by `None` for that. This means your code should look like `seq[startIndex:endIndex or None]` for example. The `or None` should be omitted if `endIndex` is expected to be positive.

#### @user2357112 2019-01-09 19:14:32

It's good to see they're not repeating Python's mistake with the -0 thing. Handling that special case is a huge hassle and way too easy to forget.

#### @programtreasures 2019-01-10 09:20:56

How can we use with dynamic keyword? like `arr[^i]` where `i` is dynamic variable

#### @Joel Mueller 2019-03-07 03:01:54

@programtreasures your first mistake was using the dynamic keyword, ever.

### [SOLVED] Array slices in C#

• 2009-01-02 10:49:05
• Matthew Scharley
• 213750 View
• 199 Score
• Tags:   c# arrays

### [SOLVED] Is there a reason that Swift array assignment is inconsistent (neither a reference nor a deep copy)?

• 2014-06-06 11:41:14
• Cthutu
• 20010 View
• 216 Score
• Tags:   arrays swift

### [SOLVED] Add a new element to an array without specifying the index in Bash

• 2009-12-23 08:59:32
• Darryl Hein
• 492137 View
• 682 Score
• Tags:   bash arrays

### [SOLVED] What is the "right" way to iterate through an array in Ruby?

• 2008-11-22 00:38:19
• Tom Lehman
• 482485 View
• 316 Score
• Tags:   ruby arrays loops

### [SOLVED] Why do indexes in XPath start with 1 and not 0?

• 2010-07-23 14:56:35
• Edward Tanguay
• 27101 View
• 100 Score
• Tags:   xslt xpath indexing