Mengapa indeks operator topi baru dari fitur slicing array # C mulai dari 0?

156

C # 8.0 memperkenalkan cara mudah untuk mengiris array - lihat blogpost resmi C # 8.0 .

Sintaks untuk mengakses elemen terakhir array adalah

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

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

Saya bertanya-tanya mengapa pengindeksan untuk mengakses elemen mundur dimulai pada 1 bukan 0? Apakah ada alasan teknis untuk ini?

Michael Pittino
sumber
11
Perhatikan bahwa rentang C ++ juga [beginInclusive, endExclusive). Itu adalah konvensi umum.
bommelding
3
@ Sinatr: Berdasarkan pada posting blog itu, sintaks untuk mengembalikan semuanya adalah value[0..^0], karena indeks akhir bersifat eksklusif (yang juga merupakan cara kerja sebagian besar bahasa lain). Juga, nyaman, value[^i..^0]akan memberi Anda iitem terakhir .
BlueRaja - Danny Pflughoeft
1
@ bommelding: C ++ rbegin()agak tidak setuju dengan gagasan itu - item pertama dari kisaran itu juga bukan yang paling luar. ;-)
DevSolar
1
Oh keren, ini mirip dengan pengindeksan negatif dalam python:value[-1] # 13
cs95
1
@coldspeed Dan di Ruby sama dengan Python. Saya kira mereka berdua meminjam konvensi ini dari Perl.
Wayne Conrad

Jawaban:

170

Jawaban resmi

Untuk visibilitas yang lebih baik, berikut adalah komentar dari Mads Torgersen yang menjelaskan keputusan desain ini dari posting blog C # 8 :

Kami memutuskan untuk mengikuti Python dalam hal aritmatika dari-awal dan dari-akhir. 0 menetapkan elemen pertama (seperti biasa), dan  ^0 elemen "length'th", yaitu elemen yang tepat dari akhir. Dengan begitu Anda mendapatkan hubungan yang sederhana, di mana posisi elemen dari awal ditambah posisinya dari ujung sama dengan panjangnya. yang  x di ^x  adalah apa yang Anda akan dikurangi dari panjang jika Anda telah melakukan matematika sendiri.

Mengapa tidak menggunakan operator minus ( -) sebagai ganti ^operator topi baru ( )? Ini terutama berkaitan dengan rentang. Sekali lagi sesuai dengan Python dan sebagian besar industri, kami ingin rentang kami inklusif pada awalnya, eksklusif pada akhirnya. Berapakah indeks yang Anda berikan untuk mengatakan bahwa rentang harus sampai akhir? Dalam C # jawabannya sederhana: x..^0mulai dari  x akhir. Dalam Python, tidak ada indeks eksplisit yang dapat Anda berikan: -0tidak berfungsi, karena sama dengan 0, elemen pertama! Jadi dengan Python, Anda harus meninggalkan indeks akhir off sepenuhnya untuk mengekspresikan berbagai yang masuk sampai akhir: x... Jika akhir rentang dihitung, maka Anda harus ingat untuk memiliki logika khusus jika itu keluar 0. Seperti dalam dihitung dan keluar kex..-y manay0. Ini adalah gangguan umum dan sumber bug.

Akhirnya, perhatikan bahwa indeks dan rentang adalah tipe kelas pertama di .NET / C #. Perilaku mereka tidak terikat pada apa yang mereka terapkan, atau bahkan untuk digunakan dalam pengindeks. Anda dapat benar-benar mendefinisikan pengindeks Anda sendiri yang mengambil Indeks dan satu lagi yang mengambil Range- dan kami akan menambahkan pengindeks tersebut untuk misalnya  Span. Tetapi Anda juga dapat memiliki metode yang mengambil rentang, misalnya.

Jawabanku

Saya pikir ini cocok dengan sintaksis klasik yang biasa kita gunakan:

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

Jika menggunakan 0, itu akan membingungkan ketika kedua sintaks digunakan berdampingan. Dengan cara ini memiliki muatan kognitif yang lebih rendah .

Bahasa lain seperti Python juga menggunakan konvensi yang sama.

Martin Zikmund
sumber
13
Koreksi kecil ke komentar Mads: Anda tidak harus meninggalkan indeks akhir sepenuhnya dalam python. Anda dapat menggunakan Nonedi tempat nomor: [0,1,2,3,4][2:None] == [2,3,4]. Tapi, ya Anda tidak bisa menggunakan integer sebagai indeks akhir (tanpa menghitung panjangnya).
Giacomo Alzetta
4
Tunggu .. ada apa dengan itu x..? Itu tampaknya baik dan saya tidak pernah punya masalah dengan [3:]sintaks python .
mowwwalker
8
@mowwwalker - bukankah itu sudah tercakup dalam kutipan? "Jadi dengan Python ... Jika akhir rentang dihitung, maka Anda harus ingat untuk memiliki logika khusus jika itu keluar ke 0"
Damien_The_Unbeliever
3
@mowwwalker komentar Mads adalah tentang kasus-kasus di mana Anda tidak tahu apa nilai indeks karena itu dihitung dalam beberapa cara. Mereka mengatakan bahwa dalam kasus Anda ingin menghitung endIndexsebagai indeks negatif (yaitu indeks dari akhir) Anda akan memiliki diskontinuitas antara angka negatif dan positif karena 0tidak akan bekerja dengan cara yang benar dalam kasus itu. Seperti yang saya menunjukkan Anda harus mengganti 0dengan Noneuntuk itu. Ini berarti kode Anda akan terlihat seperti seq[startIndex:endIndex or None]misalnya. The or Noneharus dihilangkan jika endIndexdiharapkan menjadi positif.
Giacomo Alzetta
5
Senang melihat mereka tidak mengulangi kesalahan Python dengan -0. Menangani kasus khusus itu sangat merepotkan dan terlalu mudah untuk dilupakan.
user2357112 mendukung Monica