Megosztás a következőn keresztül:


18 Kiterjesztett indexelés és szeletelés

18.1 Általános

Ez a záradék bevezet egy modellt a kiterjesztett indexelhető és szeletelhetőgyűjteménytípusokhoz , amelyek a következőre épülnek:

  • A jelen záradékban System.Index bevezetett típusok (18.2. §) és System.Range (18.3. §);
  • Az előre definiált unáris ^ (§12.9.6) és bináris .. (§12.10) operátorok; és
  • A element_access kifejezés.

A modell alatt egy típus a következő besorolású:

  • gyűjtemény, ha az s elemcsoportotjelöli
  • kiterjesztett indexelhető gyűjtemény, ha olyan element_access kifejezést támogat, amely egyetlen típusú argumentumkifejezéssel Index rendelkezik, amely a típus egyetlen elemét adja vissza és/vagy állítja be érték vagy hivatkozás alapján; és
  • kiterjesztett szeletelhető gyűjtemény, ha olyan element_access kifejezést támogat, amely egyetlen típusú Range argumentumkifejezéssel rendelkezik, amely a típus elemeinek szeletét adja vissza érték szerint.

Megjegyzés: A modell nem követeli meg, hogy a típus egy szelete be legyen állítva, de egy típus támogathatja azt a modell kiterjesztéseként. végjegyzet

A modell egydimenziós tömbök (§12.8.12.2) és sztringek (12.8.12.3. §) esetében támogatott.

A modellt bármely olyan osztály, szerkezet vagy interfésztípus támogathatja, amely megfelelő indexelőket (15.9. §) biztosít a modell szemantikájának implementálásával.

A modell implicit támogatása olyan típusok esetében biztosított, amelyek nem támogatják közvetlenül, de amelyek bizonyos tagmintát biztosítanak (18.4. §). Ez a támogatás nem szemantikai, hanem mintaalapú, mivel az alapul szolgáló típustagok szemantikája feltételezve van – a nyelv nem kényszeríti vagy ellenőrzi az ilyen típusú tagok szemantikáját.

A jelen záradék alkalmazásában a következő kifejezések vannak meghatározva:

  • A gyűjtemény olyan típus, amely az s elemcsoportotjelöli.
  • A megszámlálható gyűjtemény olyan, amely megszámlálható tulajdonságot biztosít egy int-valued instance tulajdonságnak, amelynek értéke a csoportban jelenleg található elemek száma. Ezt a tulajdonságot vagy LengthCountvagy . Az előbbi akkor lesz kiválasztva, ha mindkettő létezik.
  • A sorozat vagy indexelhető típus egy gyűjtemény:
    • amely megszámlálható;
    • ahol minden elem egyetlen kötelező int argumentummal rendelkező element_access-kifejezéssel érhető el, a kezdő index, további választható argumentumok engedélyezettek;
    • a sorozat módosítható , ha minden elem element_access kifejezéssel is beállítható;
    • egy elem kezdő indexe az N elemeket tartalmazó sorozat előtt álló elemek száma:
      • az első és az utolsó elem 0 és N-1 indexekkel rendelkezik, és
      • A múltvégi index, amely az utolsó után egy hipotetikus elemet jelöl, az N értékkel rendelkezik.
  • A végpontok közötti indexek az elemeknek a sorozaton belüli pozícióját jelölik a múltbeli indexhez képest. Az N elemeket tartalmazó sorozatok esetében az első, az utolsó és a múltbéli indexek az N, az 1 és a 0.
  • A tartomány nulla vagy több index egybefüggő futtatása, amely egy sorozat bármely indexén kezdődik.
  • A szelet egy tartományon belüli elemek gyűjteménye.
  • A szeletelhető gyűjtemények az alábbiak:
    • megszámlálható;
    • egy olyan metódust Slice biztosít, amely két int paramétert határoz meg, amelyek egy tartományt határoznak meg, kezdő indexként és elemszámként, és a tartomány elemeiből létrehozott új szeletet ad vissza.

A fenti definíciók a következőkre IndexRange terjednek ki:

  • A típus akkor is sorozat, ha egy element_access kifejezés argumentum helyett Index egyetlen kötelező int argumentumot használ. Ha különbséget kell tenni, a típust kiterjesztett indexelhetőnek nevezzük.
  • A típus akkor is szeletelhető , ha egy element_access kifejezés, amely egyetlen kötelező Range argumentumot, inkább metódust Slice használ, támogatott. Ha különbséget kell tenni, a típust kiterjesztett szeletelhetőnek nevezzük.

Az, hogy egy típus megszámlálható, indexelhető vagy szeletelhetőként van-e besorolva, a tagok akadálymentességének korlátozásai (7.5. §) vonatkoznak, ezért attól függ, hogy hol használják a típust.

Példa: Az a típus, amelyben a megszámlálható tulajdonság és/vagy az indexelő protected csak a tagok és a származtatott típusok sorozata. záró példa

A sorozatnak vagy szeletelhetőnek minősülő típushoz szükséges tagok öröklődhetnek.

Példa: Az alábbi kódban

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) { … }
}

A típus A megszámlálható, B egy sorozat, C szeletelhető és sorozat.

záró példa

Note:

  • Egy típus (akadálymentes) indexelő hiánya miatt anélkül szeletelhető, hogy indexelhető lenne.
  • Ahhoz, hogy egy típus szeletelhető és/vagy indexelhető legyen, meg kell számolni a típust.
  • Bár a sorozat elemei a sorrenden belüli pozíció alapján vannak rendezve, az elemeket nem kell az értékük szerint rendezni, vagy akár rendezhetőnek is kell lenniük.

végjegyzet

18.2 Az index típusa

A System.Index típus egy absztrakt indexet jelöl, amely egy kezdő vagy egy végponti indexet jelöl.

    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 az értékek egy int, a nem negatív eltolást megjelölő és egy boolértékből jönnek létre, amely azt jelzi, hogy az eltolás a végtől (true) vagy a kezdettől (false) származik-e. Ha a megadott eltolás negatív ArgumentOutOfRangeException , a függvény eldobja.

Example

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 ArgumentOutOfRangeException

záró példa

Van egy implicit konverzió intIndex , amelyből kiinduló indexeket hoz létre, és egy nyelv által definiált, nem szereplő operátor ^ (12.9.6. §), amelyből intIndex végponti indexeket állít elő.

Example

Implicit konverziók és a unary ^ operátor használatával a fenti példák írhatók:

Index first = 0; // first element index
var last = ^1;   // last element index
var past = ^0;   // past-end index

záró példa

A metódus GetOffset absztrakt Index értékről egy konkrét int indexértékre konvertálja a megadott lengthsorozatot. Ha az Index érték a végponttól származik, Iakkor ez a metódus ugyanazt az értéket adja vissza, mint length - I.Valueaz érték, ellenkező esetben ugyanazt az értéket adja vissza, mint I.Valuea .

Ez a módszer nem ellenőrzi, hogy a visszatérési érték az átvitt 0 érték érvényes tartományában length-1 van-e.

Jegyzet: Nincs megadva ellenőrzés, mivel az eredmény várt használata az elemeket tartalmazó length sorozatba való indexelés, és az indexelési művelet várhatóan elvégzi a megfelelő ellenőrzéseket. végjegyzet

Index az absztrakciós értéken alapuló egyenlőség esetén a megvalósítások IEquatable<Index> és értékek összehasonlíthatók; két Index érték egyenlő, ha és csak akkor, ha a megfelelő Value és IsFromEnd a tulajdonságok azonosak. Az értékek azonban Index nincsenek rendezve, és nincs más összehasonlítási művelet.

Jegyzet:Index az értékek rendezetlenek, mivel absztrakciós indexek, általában lehetetlen meghatározni, hogy egy végponti index a kezdő index előtt vagy után érkezik-e, anélkül, hogy a sorozat hosszára hivatkoznának. Miután konkrét indexekké alakították át, például a GetOffsetkonkrét indexek összehasonlíthatók. végjegyzet

Indexértékek közvetlenül használhatók egy element_access kifejezés argument_list (12.8.12. §), amely a következő:

  • a tömbhozzáférés és a cél egydimenziós tömb (12.8.12.2. §);
  • sztringhozzáférés (§12.8.12.3)
  • az indexelő hozzáférés és a céltípus rendelkezik egy indexelővel, amelynek megfelelő paraméterei vagy Index típusa (12.8.12.4. §), vagy olyan típus, amelyhez Index az értékek implicit módon átalakíthatók; vagy
  • az indexelő hozzáférése és a céltípus megfelel egy olyan sorozatmintának, amelyhez implicit Index támogatás van megadva (18.4.2. §).

18.3 A tartomány típusa

A System.Range típus az indextől az indexig Index terjedő absztrakt es tartományt Startjelöli, de nem tartalmazza az indexetEnd.

    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 az értékek két Index értékből épülnek fel.

Example

Az alábbi példák a (int) és a Index (12.9.6. §) operátor közötti implicit átalakítást ^ használják az Index egyes Rangeértékek létrehozásához:

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`

záró példa

A nyelv által definiált operátor .. (12.10. §) értékeket Range hoz létreIndex.

Example

.. Az operátor használatával a fenti példák írhatók:

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`

záró példa

Az operandusok .. nem kötelezőek, az első alapértelmezett 0érték, a második pedig a ^0következő.

Example

A fenti példák közül öt lerövidíthető az operandusok alapértelmezett értékeire támaszkodva:

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`

záró példa

Az Rangeérték azL hosszúságra érvényes, ha:

  • a tulajdonságok RangeStart vonatkozó konkrét indexek 0 és EndL közötti tartományban vannak; és
  • a konkrét index Start nem nagyobb, mint a konkrét End

Az argumentumot tartalmazó metódus GetOffsetAndLength az absztrakt length értéket a rekord által képviselt konkrét Range értékké Range alakítja. Ha a Range metódus nem érvényes a length dobásokra ArgumentOutOfRangeExceptionvonatkozóan.

A visszaadott beton Range pólya az űrlap (S, N) egy párja, ahol:

  • S a tartomány kezdő eltolása, amely a tartomány tulajdonságának Start konkrét indexe Range; és
  • Na tartomány elemeinek száma, amely a konkrét indexek és End tulajdonságok Start közötti különbség;
  • mindkét érték kiszámítása a következőre tekintettel történik length: .

A konkrét tartomány értéke üres , ha N nulla. Az üres betontartománynak S lehet egy olyan értéke, amely megegyezik a beton múltbeli indexének (18.1. §), a nem üres tartomány nem lehet. Ha egy Range gyűjtemény szeletelésére szolgál (18.1. §) a gyűjteményre vonatkozóan érvényes és üres, akkor az eredményként kapott szelet egy üres gyűjtemény.

Jegyzet: A fentiek egyik következménye, hogy egy Range nulla értékre vonatkozó length érvényes és üres érték használható egy üres gyűjtemény szeletelésére, és üres szeletet eredményez. Ez eltér az indexeléstől, amely kivételt eredményez, ha a gyűjtemény üres. végjegyzet*

Example

A fent definiált változók használata a következővel 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 a megvalósítások IEquatable<Range> és értékek összehasonlíthatók az absztrakt értéken alapuló egyenlőség szempontjából; két Range érték egyenlő, ha és csak akkor, ha az adott Start és End a tulajdonságok absztrakt értékei egyenlők (18.2. §). Az értékek azonban Range nincsenek rendezve, és nincs más összehasonlítási művelet.

Jegyzet:Range az értékek rendezetlenek, mivel absztraktak, és nincs egyedi rendezési kapcsolat. Miután konkrét kezdetre és hosszra alakították át, például a GetOffsetAndLengthrendezési reláció definiálható. végjegyzet

Rangeértékek közvetlenül használhatók egy element_access kifejezés argument_list (12.8.12. §), amely a következő:

  • a tömbhozzáférés és a cél egydimenziós tömb (12.8.12.2. §);
  • sztringhozzáférés (12.8.12.3. §);
  • az indexelő hozzáférés és a céltípus rendelkezik egy indexelővel, amelynek megfelelő paraméterei vagy Range típusa (12.8.12.4. §), vagy olyan típus, amelyhez Range az értékek implicit módon átalakíthatók; vagy
  • indexelő hozzáférés (12.8.12.4. §) és a céltípus megfelel egy olyan sorozatmintának, amelyhez implicit Range támogatás van megadva (18.4.3. §).

18.4 Az index és a tartomány mintaalapú implicit támogatása

18.4.1 Általános

Ha az űrlap egy element_access kifejezése (E[A]), amelynek E típusa T és A egy implicit módon átalakítható Index kifejezés, nem Rangeazonosítható a következőként:

akkor implicit támogatást ad a kifejezéshez, ha T megfelel egy adott mintának. Ha T nem felel meg ennek a mintának, fordítási időhiba lép fel.

18.4.2 Implicit index támogatása

Ha bármely környezetben az űrlap egy element_access kifejezése (E[A]), amelynek E típusa T és A egyetlen kifejezés implicit módon átalakíthatóIndex; érvénytelen (18.4.1. §), akkor ha ugyanabban a kontextusban:

  • T olyan akadálymentes tagokat biztosít, aki sorozatként minősíti (18.1. §); és
  • a kifejezés E[0] érvényes, és ugyanazt az indexelőt használja, amely sorozatnak minősül T

akkor a kifejezést E[A] implicit módon támogatni kell.

A jelen standard végrehajtásának egyéb korlátozása nélkül a kifejezés értékelési sorrendjének meg kell egyeznie a következőkkel:

  1. E kiértékelésre kerül;
  2. A kiértékelésre kerül;
  3. a megszámlálható tulajdonság kiértékelése T , ha a végrehajtás megköveteli;
  4. a rendszer meghívja annak az indexelőnek a int lekérését vagy beállítását T , amelyet E[0] ugyanabban a környezetben használna.

18.4.3 Implicit tartomány támogatása

Ha bármely környezetben az űrlap egy element_access kifejezése (E[A]), amelynek E típusa T és A egyetlen kifejezés implicit módon átalakíthatóRange; érvénytelen (18.4.1. §), akkor ha ugyanabban a kontextusban:

  • T a számba vehető és a szeletelhetőként is jogosult akadálymentes tagok számára (18.1.§)

akkor a kifejezést E[A] implicit módon támogatni kell.

A jelen standard végrehajtásának egyéb korlátozása nélkül a kifejezés értékelési sorrendjének meg kell egyeznie a következőkkel:

  1. E kiértékelésre kerül;
  2. A kiértékelésre kerül;
  3. a megszámlálható tulajdonság kiértékelése T , ha a végrehajtás megköveteli;
  4. metódus Slice meghívása T .