1. ホーム
  2. c#

[解決済み] C# 8の配列スライシング機能による新しいハットオペレーターインデックスは、なぜ0から始まらないのでしょうか?

2022-04-22 15:33:02

質問

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

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

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

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

気になるのは、要素を逆からアクセスする際のインデックスが、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を使用すると、2つの構文が並んで使用されたときに混乱します。この方法では より低い 認知的負荷

Pythonなど他の言語でも同じような規約が使われています。