Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
18.1 Algemeen
Deze component introduceert een model voor uitgebreide indexeerbare en sliceerbareverzamelingstypen die zijn gebouwd op:
- De typen die in deze component zijn geïntroduceerd (
System.Index§18.2) enSystem.Range(§18.3); - De vooraf gedefinieerde unaire
^operators (§12.9.6) en binaire..operatoren (§12.10) en - De element_access-expressie .
Onder het model wordt een type geclassificeerd als:
- een verzameling als deze een groep elementenvertegenwoordigt
- een uitgebreide indexeerbare verzameling als deze een element_access-expressie ondersteunt die één argumentexpressie van het type
Indexheeft die één element van het type retourneert en/of één element van het type instelt, hetzij op waarde of op verwijzing; en - een uitgebreide sliceerbare verzameling als deze een element_access-expressie ondersteunt die één argumentexpressie van het type
Rangeheeft die een segment retourneert van de elementen van het type op waarde.
Opmerking: Voor het model is niet vereist dat een segment van het type kan worden ingesteld, maar een type kan dit ondersteunen als uitbreiding van het model. eindnotitie
Het model wordt ondersteund voor enkelvoudige matrices (§12.8.12.2) en tekenreeksen (§12.8.12.3).
Het model kan worden ondersteund door elk klasse-, struct- of interfacetype dat de juiste indexeerfuncties (§15.9) biedt die de semantiek van het model implementeren.
Impliciete ondersteuning voor het model wordt geboden voor typen die het niet rechtstreeks ondersteunen, maar die een bepaald patroon van leden bieden (§18.4). Deze ondersteuning is gebaseerd op patronen, in plaats van op semantisch, omdat de semantiek van het typeleden waarop deze is gebaseerd, wordt ervan uitgegaan dat de taal de semantiek van dit type leden niet afdwingt of controleert.
Voor de doeleinden van deze component worden de volgende voorwaarden gedefinieerd:
- Een verzameling is een type dat een groep elementenvertegenwoordigt.
- Een aftelbare verzameling is een verzameling die een aftelbare eigenschap een
inteigenschap -valued instance biedt waarvan de waarde het aantal elementen is dat zich momenteel in de groep bevindt. Deze eigenschap krijgt de naam ofLengthCount. De eerste wordt gekozen als beide bestaan. - Een reeks of indexeerbaar type is een verzameling:
- dat kan worden geteld;
- waar elk element kan worden geopend met behulp van een element_access-expressie met één vereist
intargument, zijn de vanaf-start-index, aanvullende optionele argumenten toegestaan; - een reeks kan worden gewijzigd als elk element ook kan worden ingesteld met behulp van een element_access expressie;
- De from-start-index van een element is het aantal elementen voordat dit in de reeks voorkomt, voor een reeks met N-elementen :
- de eerste en laatste elementen bevatten indexen van respectievelijk 0 en N-1, en
- de afgelopen-eindindex, een index die een hypothetisch element na het laatste element vertegenwoordigt, heeft de waarde N.
- Een from-end-index vertegenwoordigt de positie van een element binnen een reeks ten opzichte van de afgelopen-endindex. Voor een reeks met N-elementen zijn de eerste, laatste en laatste indexen respectievelijk N, 1 en 0.
- Een bereik is een aaneengesloten uitvoering van nul of meer indexen die beginnen bij een index binnen een reeks.
- Een segment is de verzameling elementen binnen een bereik.
- Een sliceerbare verzameling is een verzameling die:
- is telbaar;
- biedt een methode
Slicedie tweeintparameters gebruikt die een bereik opgeven, een beginindex en een aantal elementen zijn en een nieuw segment retourneert dat is samengesteld uit de elementen in het bereik.
De bovenstaande definities worden uitgebreid voor gebruik van Index en Range als volgt:
- Een type is ook een reeks als een element_access expressie die één vereist
Indexargument gebruikt in plaats van eenintargument, wordt ondersteund. Als een onderscheid is vereist, wordt het type uitgebreid geïndexeerd. - Een type is ook segmenteerbaar als een element_access expressie die één vereist
Rangeargument gebruikt, in plaats van eenSlicemethode, wordt ondersteund. Als een onderscheid is vereist, wordt het type uitgebreid gesegmenteerd.
Of een type is geclassificeerd als telbaar, indexeerbaar of segmenteerbaar is, is onderhevig aan de beperkingen van de toegankelijkheid van leden (§7.5) en is dus afhankelijk van waar het type wordt gebruikt.
Voorbeeld: Een type waarbij de betelbare eigenschap en/of de indexeerfunctie slechts een reeks is
protectedvoor leden van zichzelf en eventuele afgeleide typen. eindvoorbeeld
De vereiste leden voor een type dat als een reeks of slicebaar kan worden aangemerkt, kunnen worden overgenomen.
Voorbeeld: In de volgende code
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) { … } }Het type
Akan worden geteld,Bis een reeks enCis sliceerbaar en een reeks.eindvoorbeeld
Opmerking:
- Een type kan worden gesegmenteerd zonder indexeerbaar te zijn vanwege het ontbreken van een (toegankelijke) indexeerfunctie.
- Als u een type wilt segmenteerbaar en/of indexeerbaar wilt maken, moet het type worden geteld.
- Hoewel de elementen van een reeks worden geordend op positie binnen de reeks, hoeven de elementen zelf niet te worden geordend op hun waarde of zelfs op volgorde.
eindnotitie
18.2 Het indextype
Het System.Index type vertegenwoordigt een abstracte index die een beginindex of een from-end-index is.
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);
}
Indexwaarden worden samengesteld op basis van een int, waarbij de niet-negatieve verschuiving wordt opgegeven en een bool, waarmee wordt aangegeven of de offset van het einde (true) of het begin () ligt.false Als de opgegeven offset negatief is, wordt er een ArgumentOutOfRangeException gegenereerd.
Voorbeeld
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 ArgumentOutOfRangeExceptioneindvoorbeeld
Er is een impliciete conversie van intIndex waaruit van beginindexen wordt geproduceerd en een door de taal gedefinieerde unaire operator ^ (§12.9.6) van intIndex waaruit van eindindexen wordt geproduceerd.
Voorbeeld
Het gebruik van impliciete conversies en de unaire
^operator van de bovenstaande voorbeelden kan worden geschreven:Index first = 0; // first element index var last = ^1; // last element index var past = ^0; // past-end indexeindvoorbeeld
De methode GetOffset converteert van een abstracte Index waarde naar een concrete int indexwaarde voor een reeks van de opgegeven lengthwaarden. Als de Index waarde I, is van einde deze methode retourneert dezelfde waarde als length - I.Value, anders retourneert deze dezelfde waarde als I.Value.
Met deze methode wordt niet gecontroleerd of de retourwaarde zich in het geldige bereik van 0length-1 inclusief bevindt.
Notitie: Er wordt geen controle opgegeven als het verwachte gebruik van het resultaat is om te indexeren in een reeks met
lengthelementen en dat indexeringsbewerking naar verwachting de juiste controles uitvoert. eindnotitie
Index
IEquatable<Index> implementeert en waarden kunnen worden vergeleken voor gelijkheid op basis van de abstracte waarde; twee Index waarden zijn gelijk als en alleen als de respectieve Value en IsFromEnd eigenschappen gelijk zijn. Waarden worden echter Index niet geordende en er worden geen andere vergelijkingsbewerkingen verstrekt.
Notitie:
Indexwaarden zijn niet gerangschikt omdat het abstracte indexen zijn, het is in het algemeen onmogelijk om te bepalen of een van-eindindex vóór of na een beginindex komt zonder verwijzing naar een reekslengte. Zodra de index is omgezet in concrete indexen, bijvoorbeeld doorGetOffset, zijn die concrete indexen vergelijkbaar. eindnotitie
Index waarden kunnen rechtstreeks worden gebruikt in de argument_list van een element_access-expressie (§12.8.12), namelijk:
- een matrixtoegang en het doel is een enkelvoudige matrix (§12.8.12.2);
- een tekenreekstoegang (§12.8.12.3)
- een indexeerfunctietoegang en het doeltype heeft een indexeerfunctie met bijbehorende parameters van beide
Indextypen (§12.8.12.4) of van een type waarvanIndexde waarden impliciet worden omgezet; of - een indexeerfunctietoegang en het doeltype voldoet aan een reekspatroon waarvoor impliciete
Indexondersteuning is opgegeven (§18.4.2).
18.3 Het bereiktype
Het System.Range type vertegenwoordigt het abstracte bereik van Indexes van een Start index tot, maar niet inclusief, een End index.
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 waarden worden samengesteld uit twee Index waarden.
Voorbeeld
In de volgende voorbeelden wordt de impliciete conversie van
int(Index§18.2) en de^operator (§12.9.6) gebruikt om de waarden voor elk van dezeIndexRangewaarden te maken: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`eindvoorbeeld
De door de taal gedefinieerde operator .. (§12.10) maakt een Range waarde op basis van Index waarden.
Voorbeeld
Met behulp van de
..operator kunnen de bovenstaande voorbeelden worden geschreven: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`eindvoorbeeld
De operanden van .. zijn optioneel, de eerste standaard 0ingesteld op , de tweede standaardwaarde ^0.
Voorbeeld
Vijf van de bovenstaande voorbeelden kunnen worden ingekort door te vertrouwen op standaardwaarden voor operanden:
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`eindvoorbeeld
Een Range waarde is geldig met betrekking tot een lengte L als:
- de concrete indexen met betrekking tot L van de
RangeeigenschappenStartenEndbevinden zich in het bereik van 0 tot L; en - de betonindex voor
Startniet groter is dan de betonindex voorEnd
De methode GetOffsetAndLength met een argument length converteert een abstracte Range waarde naar een concrete Range waarde die wordt vertegenwoordigd door tuple. Als de methode Range niet geldig is ten opzichte length van de methode.ArgumentOutOfRangeException
De geretourneerde beton Range tuple is een paar van de vorm (S, N) waarbij:
-
Sis het beginverschil van het bereik, de concrete index voor de eigenschap van deStartRange; en -
Nis het aantal items in het bereik, het verschil tussen de concrete indexen voor deEndenStarteigenschappen; - beide waarden worden berekend met betrekking tot
length.
Een concrete bereikwaarde is leeg als N nul is. Een leeg betonbereik kan een S waarde hebben die gelijk is aan de betonverloopindex (§18.1), een niet-leeg bereik mag dat niet zijn. Wanneer een Range verzameling die wordt gebruikt om te segmenteren (§18.1) een verzameling geldig en leeg is met betrekking tot die verzameling, is het resulterende segment een lege verzameling.
Notitie: Een gevolg van het bovenstaande is dat een
Rangewaarde die geldig en leeg is met betrekking tot eenlengthnul, kan worden gebruikt om een lege verzameling te segmenteren en resulteert in een leeg segment. Dit verschilt van indexering die een uitzondering genereert als de verzameling leeg is. eindnotitie*
Voorbeeld
De hierboven gedefinieerde variabelen gebruiken met
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
IEquatable<Range> implementeert en waarden kunnen worden vergeleken voor gelijkheid op basis van de abstracte waarde; twee Range waarden zijn gelijk als en alleen als de abstracte waarden van de respectieve Start en End eigenschappen gelijk zijn (§18.2). Waarden worden echter Range niet geordende en er worden geen andere vergelijkingsbewerkingen verstrekt.
Notitie:
Rangewaarden zijn niet gerangschikt, zowel omdat ze abstract zijn en er geen unieke volgorderelatie is. Eenmaal omgezet in een concrete begin- en lengte, bijvoorbeeld doorGetOffsetAndLength, kan een ordenenrelatie worden gedefinieerd. eindnotitie
Range waarden kunnen rechtstreeks worden gebruikt in de argument_list van een element_access-expressie (§12.8.12), namelijk:
- een matrixtoegang en het doel is een enkelvoudige matrix (§12.8.12.2);
- een tekenreekstoegang (§12.8.12.3);
- een indexeerfunctietoegang en het doeltype heeft een indexeerfunctie met bijbehorende parameters van beide
Rangetypen (§12.8.12.4) of van een type waarvanRangede waarden impliciet worden omgezet; of - een indexeerfunctietoegang (§12.8.12.4) en het doeltype voldoet aan een reekspatroon waarvoor impliciete
Rangeondersteuning is opgegeven (§18.4.3).
18.4 Impliciete ondersteuning op basis van patronen voor index en bereik
18.4.1 Algemeen
Als een element_access expressie (§12.8.12) van het formulier E[A]; waarbij E het type T heeft en A één expressie impliciet converteerbaar is naar Index of Range; niet kan worden geïdentificeerd als:
- een matrixtoegang (§12.8.12.2),
- een tekenreekstoegang (§12.8.12.3) of
- een indexeerfunctietoegang (§12.8.12.4) biedt
Tgeen geschikte toegankelijke indexeerfunctie
vervolgens wordt impliciete ondersteuning voor de expressie geboden als T deze voldoet aan een bepaald patroon. Als T dit patroon niet voldoet, treedt er een compilatietijdfout op.
18.4.2 Ondersteuning voor impliciete index
Als in een context een element_access expressie (§12.8.12) van het formulier E[A]; waarbij E het type T heeft en A één expressie impliciet converteerbaar is naar Index; niet geldig is (§18.4.1), dan als in dezelfde context:
-
Tbiedt toegankelijke leden die het kwalificeren als een reeks (§18.1); en - de expressie
E[0]geldig is en dezelfde indexeerfunctie gebruikt die in aanmerking komtTals een reeks
vervolgens wordt de expressie E[A] impliciet ondersteund.
Zonder dat de uitvoeringen van deze standaard anders worden beperkt, is de volgorde van evaluatie van de expressie gelijk aan:
-
Ewordt geëvalueerd; -
Awordt geëvalueerd; - de te tellen eigenschap van
Twordt geëvalueerd, indien vereist door de implementatie; - de get or set accessor van de
intgebaseerde indexeerfunctie vanTdie wordt gebruiktE[0]in dezelfde context wordt aangeroepen.
18.4.3 Ondersteuning voor impliciet bereik
Als in een context een element_access expressie (§12.8.12) van het formulier E[A]; waarbij E het type T heeft en A één expressie impliciet converteerbaar is naar Range; niet geldig is (§18.4.1), dan als in dezelfde context:
-
Tbiedt toegankelijke leden die deze kwalificeren als zowel telbaar als slicebaar (§18.1)
vervolgens wordt de expressie E[A] impliciet ondersteund.
Zonder dat de uitvoeringen van deze standaard anders worden beperkt, is de volgorde van evaluatie van de expressie gelijk aan:
-
Ewordt geëvalueerd; -
Awordt geëvalueerd; - de te tellen eigenschap van
Twordt geëvalueerd, indien vereist door de implementatie; - de
Slicemethode wordtTaangeroepen.
ECMA C# draft specification