Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
18.1 Generale
Questa clausola introduce un modello per i tipi di raccoltaindicizzati e sezionabiliestesi basati su:
- I tipi introdotti in questa clausola ,
System.Index(§18.2) eSystem.Range(§18.3); - Operatori unari
^predefiniti (§12.9.6) e binari..(§12.10) e - Espressione element_access .
Nel modello un tipo è classificato come:
- una raccolta se rappresenta un gruppo di elementi
- una raccolta indicizzata estesa se supporta un'espressione element_access che dispone di una singola espressione di argomento di tipo
Indexche restituisce e/o imposta un singolo elemento del tipo, per valore o per riferimento; e - una raccolta con filtro dei dati estesa se supporta un'espressione element_access che dispone di un'unica espressione di argomento di tipo
Rangeche restituisce una sezione degli elementi del tipo in base al valore.
Nota: il modello non richiede che sia possibile impostare una sezione del tipo, ma un tipo può supportarlo come estensione del modello. nota finale
Il modello è supportato per matrici unidimensionali (§12.8.12.2) e stringhe (§12.8.12.3).
Il modello può essere supportato da qualsiasi classe, struct o tipo di interfaccia che fornisce indicizzatori appropriati (§15.9) che implementano la semantica del modello.
Il supporto implicito per il modello viene fornito per i tipi che non lo supportano direttamente, ma che forniscono un determinato modello di membri (§18.4). Questo supporto è basato su criteri, anziché basato sulla semantica, in quanto si presuppone la semantica dei membri di tipo su cui si basa, ovvero il linguaggio non applica o controlla la semantica di questi membri di tipo.
Ai fini di questa clausola sono definiti i termini seguenti:
- Una raccolta è un tipo che rappresenta un gruppo di elementis.
- Una raccolta conteggiabile è una che fornisce una proprietà conteggiabile di una
intproprietà dell'istanza con valori di cui il valore è il numero di elementi attualmente presenti nel gruppo. Questa proprietà deve essere denominataLengthoCount. Il primo viene scelto se esistono entrambi. - Un tipo sequenza o indicizzabile è una raccolta:
- che è conteggiabile;
- in cui è possibile accedere a ogni elemento usando un'espressione element_access con un singolo argomento obbligatorio
int, l'indice from-start, sono consentiti argomenti facoltativi aggiuntivi; - una sequenza è modificabile se ogni elemento può essere impostato anche usando un'espressione element_access ;
- L'indice dall'inizio di un elemento è il numero di elementi prima della sequenza, per una sequenza contenente N elementi:
- i primi e gli ultimi elementi hanno rispettivamente indici 0 e N-1 e
- l'indice passato, un indice che rappresenta un elemento ipotetico dopo l'ultimo, ha il valore N.
- Un indice from-end rappresenta la posizione di un elemento all'interno di una sequenza rispetto all'indice di fine precedente. Per una sequenza contenente gli N elementi il primo, l'ultimo e gli indici precedenti sono rispettivamente N, 1 e 0.
- Un intervallo è un'esecuzione contigua di zero o più indici a partire da qualsiasi indice all'interno di una sequenza.
- Una sezione è la raccolta di elementi all'interno di un intervallo.
- Una raccolta sezionabile è una delle seguenti:
- è conteggiabile;
- fornisce un metodo
Sliceche accetta dueintparametri che specificano un intervallo, ovvero un indice iniziale e un conteggio di elementi rispettivamente, e restituisce una nuova sezione costruita dagli elementi dell'intervallo.
Le definizioni precedenti vengono estese per gli usi di e Index come indicato di Range seguito:
- Un tipo è anche una sequenza se è supportata un'espressione element_access che accetta un singolo argomento obbligatorio
Index, anziché unintargomento. Se è necessaria una distinzione, il tipo è definito indicizzatore esteso. - Un tipo è anche se è supportata un'espressione element_access che accetta un singolo argomento obbligatorio
Range, anziché unSlicemetodo. Se è necessaria una distinzione, il tipo è definito sezionabile esteso.
Se un tipo è classificato come conteggiabile, indicizzabile o sezionabile è soggetto ai vincoli di accessibilità dei membri (§7.5) e quindi dipende dalla posizione in cui viene utilizzato il tipo.
Esempio: un tipo in cui la proprietà conteggiabile e/o l'indicizzatore sono
protectedsolo una sequenza ai membri di se stesso e a qualsiasi tipo derivato. esempio finale
I membri necessari per un tipo da qualificare come sequenza o sezionabile possono essere ereditati.
Esempio: nel codice seguente
public class A { public int Length { get { … } } } public class B : A { public int this(int index) { … } } public class C : B { public int[] Slice(int index, int count) { … } }Il tipo
Aè conteggiabile,Bè una sequenza edCè sezionabile e una sequenza.esempio finale
Note:
- Un tipo può essere sezionabile senza essere indicizzato a causa della mancanza di un indicizzatore (accessibile).
- Affinché un tipo possa essere sezionabile e/o indicizzabile, è necessario che il tipo sia conteggiabile.
- Mentre gli elementi di una sequenza vengono ordinati in base alla posizione all'interno della sequenza, gli elementi stessi non devono essere ordinati in base al valore o anche ordinabili.
nota finale
18.2 Tipo di indice
Il System.Index tipo rappresenta un indice astratto che rappresenta un indice from-start o un indice from-end.
public readonly struct Index : IEquatable<Index>
{
public int Value { get; }
public bool IsFromEnd { get; }
public Index(int value, bool fromEnd = false);
public static implicit operator Index(int value);
public int GetOffset(int length);
public bool Equals(Index other);
}
Index i valori vengono costruiti da un intoggetto , specificando l'offset non negativo e un boologgetto , che indica se l'offset è dalla fine (true) o dall'inizio (false). Se l'offset specificato è negativo, viene generata un'eccezione ArgumentOutOfRangeException .
Esempio
Index first = new Index(0, false); // first element index var last = new Index(1, true); // last element index var past = new Index(0, true); // past-end index Index invalid = new Index(-1); // throws ArgumentOutOfRangeExceptionesempio finale
Esiste una conversione implicita da int a Index cui produce indici dall'inizio e un operatore ^ unario definito dal linguaggio (§12.9.6) da cui int produce indici from-endIndex.
Esempio
È possibile scrivere le conversioni implicite e l'operatore unario
^gli esempi precedenti:Index first = 0; // first element index var last = ^1; // last element index var past = ^0; // past-end indexesempio finale
Il metodo GetOffset converte da un valore astratto Index a un valore di indice concreto int per una sequenza dell'oggetto specificato length. Se il Index valore , Iè from-end, questo metodo restituisce lo stesso valore di length - I.Value, in caso contrario restituisce lo stesso valore di I.Value.
Questo metodo non verifica che il valore restituito sia compreso nell'intervallo valido compreso 0length-1 tra inclusi.
Nota: Non viene specificato alcun controllo perché l'uso previsto del risultato consiste nell'indicizzare in una sequenza con
lengthelementi e l'operazione di indicizzazione deve eseguire i controlli appropriati. nota finale
Index implementa e i valori possono essere confrontati IEquatable<Index> per l'uguaglianza in base al valore astratto; due Index valori sono uguali se e solo se le rispettive Value proprietà e IsFromEnd sono uguali. Tuttavia Index , i valori non vengono ordinati e non vengono fornite altre operazioni di confronto.
Nota:
IndexI valori non sono ordinati perché sono indici astratti, è in generale impossibile determinare se un indice from-end precede o dopo un indice dall'inizio senza riferimento a una lunghezza di sequenza. Dopo la conversione in indici concreti, ad esempio perGetOffset, tali indici concreti sono confrontabili. nota finale
Index i valori possono essere usati direttamente nella argument_list di un'espressione element_access (§12.8.12), ovvero:
- un accesso a una matrice e la destinazione è una matrice unidimensionale (§12.8.12.2);
- accesso a stringhe (§12.8.12.3)
- un accesso all'indicizzatore e il tipo di destinazione dispone di un indicizzatore con parametri corrispondenti di
Indextipo (§12.8.12.4) o di un tipo a cuiIndexi valori sono convertibili in modo implicito; o - un accesso all'indicizzatore e il tipo di destinazione è conforme a un modello di sequenza per il quale è specificato il supporto implicito
Index(§18.4.2).
18.3 Tipo di intervallo
Il System.Range tipo rappresenta l'intervallo astratto di Indexes da un Start indice fino a, ma non incluso, un End indice.
public readonly struct Range : IEquatable<Index>
{
public Index Start { get; }
public Index End { get; }
public Range(Index start, Index end);
public (int Offset, int Length) GetOffsetAndLength(int length);
public bool Equals(Range other);
}
Range i valori vengono costruiti da due Index valori.
Esempio
Negli esempi seguenti viene usata la conversione implicita da
intaIndex(§18.2) e dall'operatore^(§12.9.6) per creare iIndexvalori per ogniRange:var firstQuad = new Range(0, 4); // the indices from `0` to `3` // int values impicitly convert to `Index` var nextQuad = new Range(4, 8); // the indices from `4` to `7` var wholeSeq = new Range(0, ^0); // the indices from `0` to `N-1` where `N` is the // length of the sequence wholeSeq is used with var dropFirst = new Range(1, ^0); // the indices from `1` to `N-1` var dropLast = new Range(0, ^1); // the indices from `0` to `N-2` var maybeLast = new Range(^1, 6); // the indices from `N-1` to 5 var lastTwo = new Range(^2, ^0); // the indices from `N-2` to `N-1`esempio finale
L'operatore .. definito dalla lingua (§12.10) crea un Range valore da Index valori.
Esempio
È possibile scrivere l'operatore usando l'operatore
..precedente:var firstQuad = 0..4; // the indices from `0` to `3` var nextQuad = 4..8; // the indices from `4` to `7` var wholeSeq = 0..^0; // the indices from `0` to `N-1` var dropFirst = 1..^0; // the indices from `1` to `N-1` var dropLast = 0..^1; // the indices from `0` to `N-2` var maybeLast = ^1..6; // the indices from `N-1` to 5 var lastTwo = ^2..^0; // the indices from `N-2` to `N-1`esempio finale
Gli operandi di .. sono facoltativi, il primo valore predefinito è 0, il secondo valore predefinito è ^0.
Esempio
Cinque degli esempi precedenti possono essere abbreviati basandosi sui valori predefiniti per gli operandi:
var firstQuad = ..4; // the indices from `0` to `3` var wholeSeq = ..; // the indices from `0` to `N-1` var dropFirst = 1..; // the indices from `1` to `N-1` var dropLast = ..^1; // the indices from `0` to `N-2` var lastTwo = ^2..; // the indices from `N-2` to `N-1`esempio finale
Un Range valore è valido rispetto a una lunghezza L se:
- gli indici concreti in relazione all'L
Rangedelle proprietàStarte sono compresi nell'intervallo compreso tra 0 eEnd; e - l'indice concreto per
Startnon è maggiore dell'indice concreto perEnd
Il metodo GetOffsetAndLength con un argomento length converte un valore astratto Range in un valore concreto Range rappresentato dalla tupla. Se l'oggetto Range non è valido per quanto riguarda length il metodo genera ArgumentOutOfRangeException.
La tupla concreta Range restituita è una coppia del formato (S, N) in cui:
-
Sè l'offset iniziale dell'intervallo, essendo l'indice concreto per laStartproprietà diRange; e -
Nè il numero di elementi nell'intervallo, essendo la differenza tra gli indici concreti per leEndproprietà eStart; - entrambi i valori calcolati rispetto a
length.
Un valore di intervallo concreto è vuoto se N è zero. Un intervallo concreto vuoto può avere un S valore uguale all'indice di fine passato concreto (§18.1), un intervallo non vuoto potrebbe non essere. Quando un Range oggetto utilizzato per sezionare (§18.1) una raccolta è valida e vuota rispetto a tale raccolta, la sezione risultante è una raccolta vuota.
Nota: Una conseguenza di quanto sopra è che un
Rangevalore valido e vuoto rispetto a zerolengthpuò essere usato per sezionare una raccolta vuota e comporta una sezione vuota. Ciò è diverso dall'indicizzazione che genera un'eccezione se la raccolta è vuota. nota finale*
Esempio
Uso delle variabili definite in precedenza con
GetOffSetAndLength(6):var (ix0, len0) = firstQuad.GetOffsetAndLength(6); // ix0 = 0, len0 = 4 var (ix1, len1) = nextQuad.GetOffsetAndLength(6); // throws // ArgumentOutOfRangeException as range crosses sequence end var (ix2, len2) = wholeSeq.GetOffsetAndLength(6); // ix2 = 0, len2 = 6 var (ix3, len3) = dropFirst.GetOffsetAndLength(6); // ix3 = 1, len3 = 5 var (ix4, len4) = dropLast.GetOffsetAndLength(6); // ix4 = 0, len4 = 5 var (ix5, len5) = maybeLast.GetOffsetAndLength(6); // ix5 = 5, len5 = 1 var (ix6, len6) = lastTwo.GetOffsetAndLength(6); // ix6 = 4, len6 = 2
Rangeimplementa e i valori possono essere confrontati per l'uguaglianza in base al valore astratto; due IEquatable<Range> valori sono uguali se e solo se i valori astratti Range delle rispettive Start proprietà sono End uguali (§18.2). Tuttavia Range , i valori non vengono ordinati e non vengono fornite altre operazioni di confronto.
Nota:
Rangei valori non sono ordinati sia come sono astratti che non esiste alcuna relazione di ordinamento univoca. Una volta convertito in un inizio e una lunghezza concrete, ad esempioGetOffsetAndLength, è possibile definire una relazione di ordinamento. nota finale
Range I valori possono essere usati direttamente nella argument_list di un'espressione element_access (§12.8.12), ovvero:
- un accesso a una matrice e la destinazione è una matrice unidimensionale (§12.8.12.2);
- accesso a stringhe (§12.8.12.3);
- un accesso all'indicizzatore e il tipo di destinazione dispone di un indicizzatore con parametri corrispondenti di
Rangetipo (§12.8.12.4) o di un tipo a cuiRangei valori sono convertibili in modo implicito; o - un accesso indicizzatore (§12.8.12.4) e il tipo di destinazione è conforme a un modello di sequenza per il quale è specificato il supporto implicito
Range(§18.4.3).
Supporto implicito basato su pattern 18.4 per indice e intervallo
18.4.1 Generale
Se un'espressione element_access (§12.8.12) del formato E[A]; dove E ha tipo T ed A è una singola espressione convertibile Index in modo implicito in o Range; non può essere identificata come:
- accesso a una matrice (§12.8.12.2),
- accesso a stringhe (§12.8.12.3) o
- accesso dell'indicizzatore (§12.8.12.4) perché
Tnon fornisce un indicizzatore accessibile adatto
il supporto implicito per l'espressione viene quindi fornito se T è conforme a un modello specifico. Se T non è conforme a questo modello, si verifica un errore in fase di compilazione.
Supporto dell'indice implicito 18.4.2
Se in qualsiasi contesto un'espressione element_access (§12.8.12) del formato E[A]; dove E ha tipo T e A è una singola espressione convertibile in modo implicito in Index; non è valida (§18.4.1) se nello stesso contesto:
-
Tfornisce membri accessibili che lo qualificano come sequenza (§18.1); e - l'espressione
E[0]è valida e usa lo stesso indicizzatore qualificatoTcome sequenza
quindi l'espressione E[A] deve essere supportata in modo implicito.
Senza limitare altrimenti le implementazioni di questo standard, l'ordine di valutazione dell'espressione deve essere equivalente a:
-
Eviene valutato; -
Aviene valutato; - la proprietà countable di
Tviene valutata, se richiesta dall'implementazione; - viene richiamata la funzione di accesso get o set dell'indicizzatore
intbasato diTche verrebbe usata daE[0]nello stesso contesto.
Supporto dell'intervallo implicito 18.4.3
Se in qualsiasi contesto un'espressione element_access (§12.8.12) del formato E[A]; dove E ha tipo T e A è una singola espressione convertibile in modo implicito in Range; non è valida (§18.4.1) se nello stesso contesto:
-
Tfornisce membri accessibili che lo qualificano sia come conteggiabile che come sezionabile (§18.1)
quindi l'espressione E[A] deve essere supportata in modo implicito.
Senza limitare altrimenti le implementazioni di questo standard, l'ordine di valutazione dell'espressione deve essere equivalente a:
-
Eviene valutato; -
Aviene valutato; - la proprietà countable di
Tviene valutata, se richiesta dall'implementazione; - viene richiamato il
Slicemetodo diT.
ECMA C# draft specification