Perché il nuovo indice cappello-operatore dalla funzione di suddivisione in array C # 8 non inizia da 0?


156

C # 8.0 introduce un modo conveniente per tagliare le matrici - vedi il blogpost ufficiale di C # 8.0 .

La sintassi per accedere all'ultimo elemento di un array è

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

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

Mi chiedo perché l'indicizzazione per accedere agli elementi all'indietro inizi da 1 anziché 0? C'è un motivo tecnico per questo?


11
Si noti che lo sono anche gli intervalli C ++ [beginInclusive, endExclusive). È una convenzione comune.
Bommelding

3
@Sinatr: in base a quel post sul blog, la sintassi per restituire tutto sarebbe value[0..^0], poiché l'indice finale è esclusivo (che è anche il modo in cui funzionano anche le altre lingue). Inoltre, convenientemente, value[^i..^0]ti darà gli ultimi ioggetti.
BlueRaja - Danny Pflughoeft

1
@bommelding: C ++ in rbegin()qualche modo non è d'accordo con quella nozione - il primo elemento al di fuori di quell'intervallo non è neanche uno oltre il limite. ;-)
DevSolar

1
Oh bene, questo sembra l'equivalente dell'indicizzazione negativa in python:value[-1] # 13
cs95

1
@coldspeed E in Ruby lo stesso di Python. Immagino che entrambi abbiano preso in prestito questa convenzione da Perl.
Wayne Conrad,

Risposte:


170

Risposta ufficiale

Per una migliore visibilità, ecco un commento di Mads Torgersen che spiega questa decisione progettuale dal post del blog C # 8 :

Abbiamo deciso di seguire Python per quanto riguarda l'aritmetica dall'inizio e dalla fine. 0 designa il primo elemento (come sempre) e  ^0 l'elemento "lunghezza", cioè quello giusto alla fine. In questo modo si ottiene una relazione semplice, in cui la posizione di un elemento dall'inizio più la sua posizione dalla fine è uguale alla lunghezza. l'  x in  ^x è ciò che avresti sottratto dalla lunghezza se avessi fatto tu la matematica da solo.

Perché non usare il meno ( -) invece del nuovo ^operatore hat ( )? Ciò ha a che fare principalmente con le gamme. Sempre in linea con Python e la maggior parte del settore, vogliamo che le nostre gamme siano inclusive all'inizio, esclusive alla fine. Qual è l'indice che passi per dire che un intervallo dovrebbe andare fino in fondo? In C # la risposta è semplice: x..^0va dalla  x fine. In Python non esiste un indice esplicito che puoi dare: -0non funziona, perché è uguale al 0primo elemento! Quindi, in Python, si deve lasciare l'indice end fuori completamente per esprimere una gamma che va fino alla fine: x... Se viene calcolata la fine dell'intervallo, è necessario ricordare di avere una logica speciale nel caso in cui venga rilevata 0. Come in x..-y, doveyè stato calcolato ed è venuto fuori 0. Questo è un fastidio comune e fonte di bug.

Infine, si noti che gli indici e gli intervalli sono tipi di prima classe in .NET / C #. Il loro comportamento non è legato a ciò a cui sono applicati o addirittura da utilizzare in un indicizzatore. Puoi definire totalmente il tuo indicizzatore che prende Index e un altro che prende Range- e aggiungeremo tali indicizzatori ad es  Span. Ma puoi anche avere metodi che prendono intervalli, per esempio.

La mia risposta

Penso che questo corrisponda alla sintassi classica a cui siamo abituati:

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

Se usasse 0, sarebbe confuso quando le due sintassi fossero usate fianco a fianco. In questo modo ha un carico cognitivo inferiore .

Anche altre lingue come Python usano la stessa convenzione.


13
Piccola correzione al commento di Mads: non è necessario lasciare completamente l'indice di fine in Python. È possibile utilizzare Noneal posto di un numero: [0,1,2,3,4][2:None] == [2,3,4]. Sì, sì, non è possibile utilizzare un numero intero come indice finale (senza calcolare ovviamente la lunghezza).
Giacomo Alzetta,

4
Aspetta .. cosa c'è che non va x..? Sembra perfetto e non ho mai avuto problemi con la [3:]sintassi di Python .
mowwwalker,

8
@mowwwalker - non è già coperto dalla citazione? "Quindi in Python ... Se viene calcolata la fine dell'intervallo, allora devi ricordarti di avere una logica speciale nel caso in cui esca a 0"
Damien_The_Unbeliever

3
Il commento di @mowwwalker Mads riguardava casi in cui non si sa quale sarà il valore dell'indice perché viene calcolato in qualche modo. Stanno dicendo che nel caso in cui si desideri calcolare endIndexcome indice negativo (cioè indice dalla fine) si avrà una discontinuità tra numeri negativi e positivi perché 0in quel caso non funzionerà nel modo corretto. Come ho sottolineato, devi sostituirlo 0con Nonequello. Questo significa che il tuo codice dovrebbe apparire come seq[startIndex:endIndex or None]per esempio. Il or Nonedovrebbe essere omesso se endIndexsi pensa che essere positivo.
Giacomo Alzetta,

5
È bello vedere che non ripetono l'errore di Python con la cosa -0. Gestire quel caso speciale è una seccatura enorme e troppo facile da dimenticare.
user2357112 supporta Monica
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.