C#8の配列スライス機能からの新しい帽子オペレーターのインデックスが0から開始しないのはなぜですか?


156

C#8.0では、配列をスライスする便利な方法が導入されています- 公式のC#8.0ブログポストを参照してください。

配列の最後の要素にアクセスする構文は次のとおりです

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

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

要素に逆方向にアクセスするためのインデックス付けが、0ではなく1から始まるのはなぜですか。これには技術的な理由がありますか?


11
C ++の範囲もであることに注意してください[beginInclusive, endExclusive)。これは一般的な慣習です。
1

3
@Sinatr:そのブログ投稿に基づくとvalue[0..^0]、終了インデックスが排他的であるため、すべてを返す構文はになります(これは他のほとんどの言語でも同様です)。また、便利なvalue[^i..^0]ことに、最後のiアイテムを提供します。
BlueRaja-Danny Pflughoeft

1
@bommelding:C ++ rbegin()はその概念にいくらか反対しています-その範囲外の最初の項目も、終わりを超えたものではありません。;-)
DevSolar

1
ああ、これはpythonの負のインデックスに相当するように見えます:value[-1] # 13
cs95

1
@coldspeedそしてRubyではPythonと同じです。私は彼らが両方ともPerlからこの規約を借りたと思います。
ウェインコンラッド

回答:


170

公式回答

見やすくするために、C#8ブログ投稿からのこの設計決定を説明するMads Torgersenからのコメントを次に示します。

始点演算と終点演算については、Pythonに従うことを決定しました。 0 (いつものように)最初の要素と^0 「長さ」の要素、つまり最後から1つ目の要素を指定し  ます。このようにすると、要素の最初からの位置と最後からの位置の合計が長さに等しい単純な関係が得られます。 x 中には、  ^x あなたが数学を自分で行わたい場合、あなたは長さから差し引かであろうものです。

-新しいハット(^)演算子の代わりにマイナス()を使用しないのはなぜですか?これは主に範囲に関係しています。繰り返しになりますが、Pythonおよび業界のほとんどと同様に、範囲を最初は包括的に、最後は排他的にしたいと考えています。範囲は最後まで行くべきだと言うために渡すインデックスは何ですか?C#では、答えは簡単です 。最後x..^0から  x最後までです。Pythonでは、指定できる明示的なインデックスはあり-0ません0。最初の要素と等しいため、機能しません。したがって、Pythonでは、最後まで続く範囲を表すために、終了インデックスを完全にオフにする必要がありますx..。範囲の終わりが計算された場合、それがに出た場合に備えて、特別なロジックを持つことを忘れないでください0。のようにx..-y、どこy計算され、に出てきました0。これは一般的な迷惑であり、バグの原因です。

最後に、インデックスと範囲は.NET / C#の最初のクラスタイプであることに注意してください。それらの動作は、それらが適用されるもの、またはインデクサーで使用されるものとは関係ありません。Indexを使用する独自のインデクサーと、それを使用する別のインデクサーを完全に定義できます。Rangeこのようなインデクサーをegなどに追加します  Span。しかし、たとえば、範囲を取るメソッドを持つこともできます。

私の答え

これは、私たちが慣れている古典的な構文と一致するためだと思います。

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

0を使用する場合、2つの構文を並べて使用すると混乱を招きます。この方法では認知負荷が低くなります。

Pythonなどの他の言語でも同じ規則が使用されます。


13
Madsコメントのマイナーな修正:Pythonで終了インデックスを完全に省略する必要はありませんNone番号の代わりに使用できます:[0,1,2,3,4][2:None] == [2,3,4]。しかし、はい、整数を終了インデックスとして使用することはできません(長さを明らかに計算しない限り)。
ジャコモアルゼッタ

4
待って..何が悪いのx..?それは問題ないようで、私はpython [3:]構文に問題があったことがありません。
mowwwalker

8
@mowwwalker-それはすでに見積もりに含まれていませんか?「Pythonでは...範囲の終わりが計算された場合、0になった場合に備えて特別なロジックがあることを覚えておく必要があります
Damien_The_Unbeliever

3
@mowwwalker Madsのコメントは、何らかの方法で計算されたために、インデックス値がどうなるかわからない場合についてのものでした。彼らはendIndex、負のインデックス(つまり、最後からのインデックス)として計算したい場合、は正数と負数の間に不連続があると言っています0。私が指摘したように、あなたは交換する必要が0Noneているため。つまり、コードは次のようseq[startIndex:endIndex or None]になります。or None場合は省略されなければならないendIndex陽性であることが期待されています。
ジャコモアルゼッタ

5
彼らが-0のことでPythonの間違いを繰り返さないのは良いことです。その特別なケースを処理することは非常に面倒であり、忘れがたいほど簡単です。
user2357112は
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.