Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
18.1 Obecné
Tato klauzule zavádí model pro rozšířené indexovatelné a průřezové typy kolekcí založené na těchto typech:
- Typy uvedené v této klauzuli
System.Index(§18.2) aSystem.Range(§18.3); - Předdefinované unární
^operátory (§12.9.6) a binární..operátory (§12.10) a - Výraz element_access .
Pod modelem je typ klasifikován jako:
- a collection if it represent a group of elements
-
rozšířenou indexovatelnou kolekci, pokud podporuje výraz element_access, který má jediný argument výraz typu
Index, který vrací nebo nastaví jeden prvek typu, a to buď podle hodnoty, nebo odkazu; -
rozšířenou kolekci s možností průřezu, pokud podporuje výraz element_access, který má jediný argumentový výraz typu
Range, který vrací řez prvků typu podle hodnoty.
Poznámka: Model nevyžaduje, aby byl řez typu nastaven, ale typ ho může podporovat jako rozšíření modelu. koncová poznámka
Model je podporován pro jednorozměrná pole (§12.8.12.2) a řetězce (§12.8.12.3).
Model může být podporován jakoukoli třídou, strukturou nebo typem rozhraní, které poskytují vhodné indexery (§15.9), které implementují sémantiku modelu.
Implicitní podpora modelu je poskytována pro typy, které jej přímo nepodporují, ale které poskytují určitý vzor členů (§18.4). Tato podpora je založená na vzorech, nikoli na sémantickém základě, protože se předpokládá sémantika členů typu, na kterých je založená , – jazyk nevynucuje ani nekontroluje sémantiku těchto členů typu.
Pro účely této klauzule jsou definovány následující termíny:
- Kolekce je typ, který představuje skupinu prvků.
-
Počítaná kolekce je jedna, která poskytuje počítanou vlastnost
int-valued instance, jejíž hodnota je počet prvků aktuálně ve skupině. Tato vlastnost má název buďLengthneboCount. První možnost je zvolena, pokud existují obě. -
Posloupnost nebo indexovatelný typ je kolekce:
- což je počítáno;
- kde každý prvek lze získat přístup pomocí výrazu element_access s jedním povinným
intargumentem, index from-start, další volitelné argumenty jsou povoleny; - sekvence je upravitelná , pokud lze každý prvek nastavit také pomocí výrazu element_access ;
- Index od začátku prvku je počet prvků před ním v posloupnosti pro sekvenci obsahující prvky N :
- první a poslední prvky mají indexy 0 a N-1 a
- index, který představuje hypotetický prvek za posledním indexem, má hodnotu N.
- Od-endový index představuje pozici elementu v posloupnosti vzhledem k předchozímu indexu. Pro sekvenci obsahující N prvků jsou první, poslední a poslední-endové indexy N, 1 a 0 v uvedeném pořadí.
- Rozsah je souvislý běh nulových nebo více indexů začínajících v libovolném indexu v posloupnosti.
- Řez je kolekce prvků v rozsahu.
-
Průřezová kolekce je ta, která:
- je počítán;
- poskytuje metodu
Slice, která přebírá dvaintparametry určující rozsah, jako počáteční index a počet prvků v uvedeném pořadí, a vrátí nový řez vytvořený z prvků v oblasti.
Výše uvedené definice jsou rozšířeny pro použití Index a Range následujícím způsobem:
- Typ je také posloupnost , pokud je podporován výraz element_access s jedním povinným
Indexargumentem, nikoli argumentemint. V případě, že je požadováno rozlišení, je typ označen jako rozšířený indexable. - Typ je také průřezovatelný , pokud je podporován výraz element_access s jedním povinným
Rangeargumentem, spíše metodouSlice. V případě, že je požadováno rozlišení, je typ označen jako rozšířený průřez.
Určuje, zda je typ klasifikován jako počítaný, indexovatelný nebo průřez, podléhá omezením přístupnosti členů (§7.5), a proto závisí na tom, kde se typ používá.
Příklad: Typ, ve kterém je počítaná vlastnost nebo indexer
protected, je pouze posloupnost členů samotného a všech odvozených typů. konec příkladu
Požadované členy pro typ, které se dají kvalifikovat jako posloupnost nebo průřez, mohou být zděděné.
příklad: V následujícím kódu
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) { … } }Typ
Aje počítán,Bje posloupnost aCje průřez a posloupnost.konec příkladu
Poznámka:
- Typ může být průřezový, aniž by byl indexovatelný kvůli nedostatku indexeru (přístupného).
- Aby byl typ průřezový nebo indexovatelný, vyžaduje, aby byl typ počítán.
- Zatímco prvky sekvence jsou seřazeny podle pozice v posloupnosti, samotné prvky nemusí být seřazeny podle jejich hodnoty nebo dokonce seřazené.
koncová poznámka
18.2 Typ indexu
Typ System.Index představuje abstraktní index, který představuje index od začátku nebo od koncového indexu.
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 hodnoty jsou tvořeny z inthodnoty , určení ne záporného posunu a a bool, označující, zda je posun od konce (true) nebo začátku (false). Pokud je zadaný posun záporný, ArgumentOutOfRangeException vyvolá se.
Příklad
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 ArgumentOutOfRangeExceptionkonec příkladu
Existuje implicitní převod, ze intIndex kterého vznikají počáteční indexy, a jazykově definovaný unární operátor ^ (§12.9.6), ze intIndex kterého se vytváří indexy od konce.
Příklad
Pomocí implicitních převodů a unárního
^operátoru mohou být zapsány výše uvedené příklady:Index first = 0; // first element index var last = ^1; // last element index var past = ^0; // past-end indexkonec příkladu
Metoda GetOffset převede z abstraktní Index hodnoty na konkrétní int hodnotu indexu pro sekvenci zadaného length. Pokud hodnota Index , Ije od-end tato metoda vrátí stejnou hodnotu jako length - I.Value, jinak vrátí stejnou hodnotu jako I.Value.
Tato metoda nekontroluje , že vrácená hodnota je v platném rozsahu 0 až length-1 včetně.
Poznámka: Není zadána žádná kontrola, protože očekávané použití výsledku je indexovat do sekvence s
lengthprvky a že se očekává, že operace indexování provede příslušné kontroly. koncová poznámka
Index implements IEquatable<Index> and values may be compared for equal on the abstract value; two Index values are equal if and only if the respective Value and IsFromEnd properties are equal. Hodnoty ale Index nejsou seřazené a nejsou k dispozici žádné jiné operace porovnání.
Poznámka:
Indexhodnoty jsou neuspořádané, protože jsou abstraktní indexy, obecně není možné určit, zda před nebo po počátečním indexu pochází před nebo po počátečním indexu bez odkazu na délku sekvence. Po převodu na konkrétní indexy jsou tytoGetOffsetkonkrétní indexy srovnatelné. koncová poznámka
Index hodnoty mohou být použity přímo ve argument_listvýrazu element_access (§12.8.12), který je:
- přístup k poli a cíl je jednorozměrná matice (§12.8.12.2);
- přístup k řetězci (§12.8.12.3)
- přístup k indexeru a cílový typ má indexer s odpovídajícími parametry typu
Index(§12.8.12.4) nebo typu, na kterýIndexjsou hodnoty implicitně konvertibilní; - přístup indexeru a cílový typ odpovídá sekvenci, pro který je určena implicitní
Indexpodpora (§18.4.2).
18.3 Typ rozsahu
Typ System.Range představuje abstraktní rozsah hodnot z indexu IndexStart až do indexu, ale ne zahrnutí indexuEnd.
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 hodnoty jsou tvořeny ze dvou Index hodnot.
Příklad
Následující příklady používají implicitní převod na
intIndex(§18.2) a^operátor (§12.9.6) k vytvořeníIndexhodnot pro každýRange: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`konec příkladu
Operátor definovaný .. jazykem (§12.10) vytvoří Range hodnotu z Index hodnot.
Příklad
Použití operátoru
..výše uvedených příkladů může být zapsáno: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`konec příkladu
Operandy .. jsou volitelné, první výchozí hodnota 0, druhá výchozí hodnota ^0.
Příklad
Pět z výše uvedených příkladů je možné zkrátit tím, že se spoléhá na výchozí hodnoty pro operandy:
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`konec příkladu
Hodnota Range je platná s ohledem na délku L , pokud:
- konkrétní indexy s ohledem na L
RangevlastnostíStartaEndjsou v rozsahu 0 až L; a - konkrétní index
Startnení větší než konkrétní index proEnd
Metoda GetOffsetAndLength s argumentem length převede abstraktní Range hodnotu na konkrétní Range hodnotu reprezentovanou řazenou kolekcí členů.
Range Pokud není platný s ohledem na length metodu vyvolá ArgumentOutOfRangeException.
Vrácená betonová Range řazená kolekce členů je dvojice formuláře (S, N) , kde:
-
Sje počáteční posun rozsahu, který je betonovým indexemStartpro vlastnostRange; a -
Nje počet položek v rozsahu, přičemž je rozdíl mezi konkrétními indexy proEndvlastnosti aStartvlastnostmi; - obě hodnoty se počítají s ohledem na
length.
Konkrétní hodnota rozsahu je prázdná , pokud N je nula. Prázdný rozsah betonu S může mít hodnotu rovnající se konkrétnímu minulému indexu (§18.1), neprázdný rozsah nesmí. Pokud je kolekce použitá Range k řezu (§18.1), je kolekce platná a prázdná s ohledem na tuto kolekci, je výsledný řez prázdnou kolekcí.
Poznámka: Výsledkem výše uvedeného je, že
Rangehodnota, která je platná a prázdná s ohledem na nululength, může být použita k řezu prázdné kolekce a výsledkem je prázdný řez. Liší se od indexování, které vyvolá výjimku, pokud je kolekce prázdná. koncová poznámka*
Příklad
Použití výše definovaných proměnných s
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
Range implements IEquatable<Range> and values may be compared for equal on the abstract value; two Range values are equal if and only if the abstract values of the respective Start and End properties are equal (§18.2). Hodnoty ale Range nejsou seřazené a nejsou k dispozici žádné jiné operace porovnání.
Poznámka:
Rangehodnoty jsou neuspořádané, protože jsou abstraktní a neexistuje žádná jedinečná relace řazení. Po převodu na konkrétní začátek a délku můžeGetOffsetAndLengthbýt definována například relace řazení. koncová poznámka
Range hodnoty lze použít přímo ve argument_listvýrazu element_access (§12.8.12), který je:
- přístup k poli a cíl je jednorozměrná matice (§12.8.12.2);
- přístup k řetězci (§12.8.12.3);
- přístup k indexeru a cílový typ má indexer s odpovídajícími parametry typu
Range(§12.8.12.4) nebo typu, na kterýRangejsou hodnoty implicitně konvertibilní; - přístup indexeru (§12.8.12.4) a cílový typ odpovídá sekvenci, pro který je zadána implicitní
Rangepodpora (§18.4.3).
18.4 Implicitní podpora založené na vzorech pro index a rozsah
18.4.1 Obecné
Je-li výraz element_access (§12.8.12) formuláře E[A]; pokud E má typ T a A je jedním výrazem implicitně konvertibilní na Index nebo Range; nelze identifikovat jako:
- maticový přístup (§12.8.12.2),
- přístup k řetězci (§12.8.12.3) nebo
- přístup indexeru (§12.8.12.4) tak, jak
Tnení vhodný přístup k indexeru
pak je k dispozici implicitní podpora výrazu, pokud T odpovídá určitému vzoru. Pokud T tento vzor nevyhovuje, dojde k chybě v době kompilace.
Podpora implicitního indexu 18.4.2
Pokud v libovolném kontextu není výraz element_access (§12.8.12) formuláře E[A]; pokud E má typ T a A je jedním výrazem implicitně konvertibilní Indexna ; není platný (§18.4.1), pak pokud je ve stejném kontextu:
-
Tposkytuje přístupné členy, kteří je opravňující jako posloupnost (§18.1); a - výraz
E[0]je platný a používá stejný indexer, který se kvalifikujeTjako posloupnost.
pak se výraz E[A] implicitně podporuje.
Bez jinak omezujících implementací této normy se pořadí vyhodnocení výrazu rovná:
-
Evyhodnocuje se; -
Avyhodnocuje se; - počítaná vlastnost
Tse vyhodnocuje, pokud je to požadováno implementací; - Vyvolá se get nebo set přístupového objektu
intzaloženého na indexeruT, který by byl použitE[0]ve stejném kontextu.
Podpora implicitního rozsahu 18.4.3
Pokud v libovolném kontextu není výraz element_access (§12.8.12) formuláře E[A]; pokud E má typ T a A je jedním výrazem implicitně konvertibilní Rangena ; není platný (§18.4.1), pak pokud je ve stejném kontextu:
-
Tposkytuje přístupné členy, které jsou kvalifikující jako spočítatelné i průřezové (§18.1).
pak se výraz E[A] implicitně podporuje.
Bez jinak omezujících implementací této normy se pořadí vyhodnocení výrazu rovná:
-
Evyhodnocuje se; -
Avyhodnocuje se; - počítaná vlastnost
Tse vyhodnocuje, pokud je to požadováno implementací; -
SlicemetodaTje vyvolána.
ECMA C# draft specification