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


11 Minták és minták egyeztetése

11.1 Általános

A minta egy szintaktikai forma, amely az operátorral is (12.12.12.§) és egy switch_statement (13.8.3. §) használható azon adatok alakjának kifejezésére, amelyekhez a bejövő adatokat össze kell hasonlítani. A minta tesztelése egy kapcsolóutasítás kifejezésén vagy egy is történik, amelyek mindegyikét mintabemeneti értéknek nevezzük.

11.2 Mintaalakok

11.2.1 Általános

Egy minta a következő űrlapok egyikével rendelkezhet:

pattern
    : declaration_pattern
    | constant_pattern
    | var_pattern
    ;

Egy declaration_pattern és egy var_pattern helyi változó deklarációját eredményezheti.

Minden mintaűrlap meghatározza a minta által alkalmazható bemeneti értékek típusait. A minta P akkor T, ha T azon típusok közé tartozik, amelyek értékei megegyezhetnek a mintával. Fordítási idejű hiba, ha egy minta P egy olyan programban jelenik meg, amely megfelel egy minta bemeneti értékének (T. §), ha P az nem alkalmazható.T

Példa: Az alábbi példa fordítási időt eredményez, mert a fordítási idő típusa v .TextReader Egy típusú TextReader változó soha nem rendelkezhet olyan értékkel, amely hivatkozással stringkompatibilis:

TextReader v = Console.In; // compile-time type of 'v' is 'TextReader'
if (v is string) // compile-time error
{
    // code assuming v is a string
}

Az alábbiak azonban nem okoznak fordítási időt, mert a fordítási idő típusa v .object Egy típusváltozó object olyan értékkel rendelkezhet, amely hivatkozással kompatibilis a következőkkel string:

object v = Console.In;
if (v is string s)
{
    // code assuming v is a string
}

záró példa

Minden mintaűrlap meghatározza azokat az értékeket, amelyek esetében a minta futásidőben megegyezik az értékkel.

11.2.2 Deklarációs minta

Egy declaration_pattern annak ellenőrzésére szolgál, hogy egy érték adott típusú-e, és ha a teszt sikeres, adja meg az értéket egy ilyen típusú változóban.

declaration_pattern
    : type simple_designation
    ;
simple_designation
    : single_variable_designation
    ;
single_variable_designation
    : identifier
    ;

Az érték futtatókörnyezettípusát a rendszer a mintában szereplő típus alapján teszteli az is-type operátorban megadott szabályokkal (12.12.12.1. §). Ha a teszt sikeres, a minta megfelel ennek az értéknek. Fordítási idő hiba, ha a típus null értékű (8.3.12. §). Ez a mintaűrlap soha nem egyezik meg egy null értékkel.

Megjegyzés: Az is-type kifejezés e is T és a deklarációs minta e is T _ egyenértékű, ha T nem null értékű típus. végjegyzet

Ha a minta bemeneti értéke (§11.1) e, és a simple_designation a azonosító_, akkor ez az eldobást (§9.2.9.2) jelöli, és az e értéke semmihez sincs kötve. (Bár egy _ nevű deklarált változó lehet a hatókörben, az elnevezett változó ebben a kontextusban nem látható.) Ha simple_designation bármely más azonosító, a rendszer bevezet egy helyi változót (§9.2.9.1) az adott azonosító által elnevezett adott típusból. Ez a helyi változó a minta bemeneti értékének értékét rendeli hozzá, ha a minta megfelel az értéknek.

A minta bemeneti értékének és az adott típus statikus típusának bizonyos kombinációi nem kompatibilisek, és fordítási időt eredményeznek. A statikus típusú E értékeknek a típussal kompatibilisT, ha létezik identitásátalakítás, implicit vagy explicit referenciakonvertálás, dobozos átalakítás, vagy ETha nyitott ET vagy nyitott típus (8.4.3. §). A típus TE amely E a mintával Tkompatibilis.

Megjegyzés: A nyitott típusok támogatása leginkább akkor lehet hasznos, ha olyan típusokat ellenőriz, amelyek lehetnek strukturált vagy osztálytípusok, és kerülni kell a boxolást. végjegyzet

Példa: A deklarálási minta hasznos a referenciatípusok futásidejű típustesztjeihez, és lecseréli az idiómát

var v = expr as Type;
if (v != null) { /* code using v */ }

a kissé tömörebb

if (expr is Type v) { /* code using v */ }

záró példa

Hiba, ha a típus null értékű.

Példa: A deklarálási minta használható null értékű értékek tesztelésére: egy típus ( Nullable<T> vagy egy dobozos T) érték megfelel egy típusmintának T2 id , ha az érték nem null értékű, és T2 az T, vagy a típus valamilyen alaptípusa Tvagy felülete. Például a kódtöredékben

int? x = 3;
if (x is int v) { /* code using v */ }

Az utasítás állapota if futásidőben vantrue, és a változó v a blokkon belül tárolja a típus 3 értékétint. záró példa

11.2.3 Állandó minta

Egy constant_pattern egy minta bemeneti értékének (11.1. §) az adott állandó értéken való tesztelésére szolgál.

constant_pattern
    : constant_expression
    ;

Az állandó minta P akkor T, ha implicit átalakítás történik az állandó kifejezésből P a típusba T.

Állandó minta Pesetén a konvertált érték a következő:

  • ha a minta bemeneti értékének típusa integráltípus vagy számtípus, akkor a minta állandó értéke erre a típusra lesz konvertálva; egyébként
  • ha a minta bemeneti értéke egy integrál- vagy számtípus null értékű verziója, a minta állandó értéke az alapul szolgáló típussá alakul át; egyébként
  • a minta állandó értékének értéke.

Az e mintául szolgáló bemeneti érték és a konvertált v értékkel rendelkező állandó mintaP,

  • ha e integráltípussal vagy számtípussal rendelkezik, vagy az egyiknek null értékű formája van, és v integráltípussal rendelkezik, a minta P megfelel az e értéknek, ha a kifejezés e == vtrueeredménye; egyébként
  • a minta Pmegfelel az e értéknek, ha object.Equals(e, v) visszaadjatrue.

Példa: A switch következő metódusban szereplő utasítás öt állandó mintát használ a kis- és nagybetűk címkéiben.

static decimal GetGroupTicketPrice(int visitorCount)
{
    switch (visitorCount) 
    {
        case 1: return 12.0m;
        case 2: return 20.0m;
        case 3: return 27.0m;
        case 4: return 32.0m;
        case 0: return 0.0m;
        default: throw new ArgumentException(...);
    }
}

záró példa

11.2.4 Var minta

Egy var_patternminden értéknek megfelel . Ez azt jelzi, hogy egy mintaegyeztetés mindig sikeres var_pattern.

A var_patternminden típusra alkalmazható.

var_pattern
    : 'var' designation
    ;
designation
    : simple_designation
    ;

Ha a minta bemeneti értéke (§11.1) e, és a megjelölés a azonosító_, akkor visszadobást (§9.2.9.2) jelöl, és az e értéke semmihez sincs kötve. (Bár az ilyen nevű deklarált változók a hatókörben lehetnek, az elnevezett változó ebben a kontextusban nem látható.) Ha megjelölés bármely más azonosító, futásidőben az e értéke egy újonnan bevezetett helyi változóhoz (§9.2.9.1) van kötve, amelynek a típusa az e estatikus típusa, és a minta bemeneti értéke hozzá van rendelve ehhez a helyi változóhoz.

Hiba, ha a név var olyan típushoz kötődik, amelyben egy var_pattern használ.

11.3 Minta-részsumpció

A kapcsolóutasításban hiba, ha egy eset mintáját az előző, nem őrzött esetek halmaza (13.8.3. §) aláveti. Informálisan ez azt jelenti, hogy minden bemeneti érték megfelelt volna az előző esetek egyikének. A következő szabályok határozzák meg, hogy egy mintakészlet mikor ad részösszeget egy adott mintának:

A minta P akkor egyezikK

A minták Qegy halmaza alávet egy mintát P , ha az alábbi feltételek bármelyike fennáll:

  • P állandó minta, és a készlet Q bármely mintája megegyezik Pa konvertált értékével
  • P egy var minta, és a minták Qkészlete teljes (11.4. §) a minta bemeneti értékének típusához (11.1. §), és vagy a minta bemeneti értéke nem null értékű, vagy egy minta Q egyezik null.
  • P egy típussal T rendelkező deklarációs Qminta, és a minták készlete teljes a típusra T vonatkozóan (11.4. §).

11.4 Minta teljessége

Informálisan a minták egy típusra vonatkozóan teljes körűek, ha a nulltól eltérő típus minden lehetséges értékére alkalmazható valamilyen minta a készletben. Az alábbi szabályok határozzák meg, hogy egy típus esetében egy mintakészlet mikor teljes:

Egy típusra Q vonatkozó minták teljes körűekT, ha az alábbi feltételek bármelyike fennáll:

  1. T egy integrál- vagy számtípus, vagy ezek egyikének null értékű verziója, és a "nem null értékű mögöttes típus" minden lehetséges értékéhez Tbizonyos minta Q megfelelne ennek az értéknek; vagy
  2. Néhány minta Q egy var minta; vagy
  3. Néhány minta Q típus D, és van egy identitáskonverzió, implicit referenciaátalakítás, vagy egy dobozos átalakítás a típusról T a másikraD.

Példa:

static void M(byte b)
{
    switch (b) {
        case 0: case 1: case 2: ... // handle every specific value of byte
            break;
        // error: the pattern 'byte other' is subsumed by the (exhaustive)
        // previous cases
        case byte other: 
            break;
    }
}

záró példa