Sdílet prostřednictvím


17 Polí

17.1 Obecné

Pole je datová struktura, která obsahuje řadu proměnných, ke kterým se přistupuje prostřednictvím vypočítaných indexů. Proměnné obsažené v matici, označované také jako prvky pole, jsou všechny stejného typu a tento typ se nazývá typ prvku pole.

Pole má pořadí, které určuje počet indexů přidružených k jednotlivým prvkům pole. Pořadí matice se také označuje jako dimenze pole. Pole s pořadím jednoho se nazývá jednorozměrné pole. Pole s pořadím, které je větší než jedno, se nazývá multidimenzionální pole. Multidimenzionální pole se často označují jako dvojrozměrná pole, trojrozměrná pole atd. Každá dimenze pole má přidruženou délku, která je celočíselné číslo větší nebo rovno nule. Délky dimenzí nejsou součástí typu pole, ale jsou vytvořeny při vytvoření instance typu pole za běhu. Délka dimenze určuje platný rozsah indexů pro danou dimenzi: Pro dimenzi délky Nmohou indexy být v rozsahu od 0 po N – 1 inkluzivní. Celkový počet prvků v matici je součin délky každé dimenze v matici. Pokud jedna nebo více dimenzí pole má délku nuly, je pole prázdné.

Typ prvku pole může být sám o sobě typ matice (§17.2.1). Taková pole polí se liší od multidimenzionálních polí a lze je použít k reprezentaci "žloutkových polí".

Příklad:

int[][] pascals = 
{
    new int[] {1},
    new int[] {1, 1},
    new int[] {1, 2, 1},
    new int[] {1, 3, 3, 1}
};

end example

Každý typ matice je referenčním typem (§8.2). Typ prvku pole může být libovolný typ, včetně typů hodnot a typů pole.

17.2 Typy polí

17.2.1 Obecné

Gramatické produkce pro typy polí jsou uvedeny v §8.2.1.

Typ pole se zapíše jako non_array_type následuje jeden nebo více rank_specifiers.

Non_array_type je jakýkoli typ, který není sám o sobě array_type.

Pořadí typu pole je dáno úplně vlevo rank_specifier v array_type: rank_specifier označuje, že pole je matice s pořadím jednoho a počtem, tokenů v rank_specifier.

Typ prvku typu pole je typ, který je výsledkem odstranění nejvíce vlevo rank_specifier:

  • Typ pole formuláře T[R] je matice s pořadím R a typem Tprvku, který není polem .
  • Typ pole formuláře T[R][R₁]...[Rₓ] je matice s pořadím R a typem T[R₁]...[Rₓ]prvku .

Rank_specifier s se tedy čte zleva doprava před posledním typem elementu bez pole.

Příklad: Typ T[][,,][,] je jednorozměrné pole třírozměrných polí dvourozměrných polí .int end example

Za běhu může být null hodnota typu pole nebo odkaz na instanci tohoto typu pole.

Poznámka: Podle pravidel §17.6 může být hodnota také odkazem na kovariantní typ pole. koncová poznámka

17.2.2 Typ System.Array

System.Array Typ je abstraktní základní typ všech typů pole. Implicitní převod odkazu (§10.2.8) existuje z libovolného typu pole do System.Array a na jakýkoli typ rozhraní implementovaný System.Array. Explicitní převod odkazu (§10.3.5) existuje z System.Array jakéhokoli typu rozhraní implementovaného System.Array na jakýkoli typ pole. System.Array není sám o sobě array_type. Spíše je to class_type , ze kterého jsou odvozeny všechny array_types.

Za běhu může být null hodnota typu System.Array nebo odkaz na instanci libovolného typu pole.

17.2.3 Matice a obecná rozhraní kolekcí

Jednorozměrné pole T[] implementuje rozhraní System.Collections.Generic.IList<T> (IList<T> zkráceně) a jeho základní rozhraní. Proto existuje implicitní převod ze T[] základního rozhraní na IList<T> a jeho základní rozhraní. Kromě toho platí, že pokud existuje implicitní převod odkazu z do té 10.2.8 IList<T> a existuje implicitní převod odkazu z IList<T> S[] a jeho základního rozhraní (§10.2.8).S[] T S Je-li zde explicitní odkaz na S T převod, existuje-li explicitní převod odkazu z IList<T> S[] a jeho základního rozhraní (§10.3.5).

Podobně jednorozměrné pole T[] také implementuje rozhraní System.Collections.Generic.IReadOnlyList<T> (IReadOnlyList<T> zkráceně) a jeho základní rozhraní. Proto existuje implicitní převod ze T[] základního rozhraní na IReadOnlyList<T> a jeho základní rozhraní. Kromě toho platí, že pokud existuje implicitní převod odkazu z do té 10.2.8 IReadOnlyList<T> a existuje implicitní převod odkazu z IReadOnlyList<T> S[] a jeho základního rozhraní (§10.2.8).S[] T S Je-li zde explicitní odkaz na S T převod, existuje-li explicitní převod odkazu z IReadOnlyList<T> S[] a jeho základního rozhraní (§10.3.5).

Příklad: Příklad:

class Test
{
    static void Main()
    {
        string[] sa = new string[5];
        object[] oa1 = new object[5];
        object[] oa2 = sa;

        IList<string> lst1 = sa;  // Ok
        IList<string> lst2 = oa1; // Error, cast needed
        IList<object> lst3 = sa;  // Ok
        IList<object> lst4 = oa1; // Ok

        IList<string> lst5 = (IList<string>)oa1; // Exception
        IList<string> lst6 = (IList<string>)oa2; // Ok

        IReadOnlyList<string> lst7 = sa;        // Ok
        IReadOnlyList<string> lst8 = oa1;       // Error, cast needed
        IReadOnlyList<object> lst9 = sa;        // Ok
        IReadOnlyList<object> lst10 = oa1;      // Ok
        IReadOnlyList<string> lst11 = (IReadOnlyList<string>)oa1; // Exception
        IReadOnlyList<string> lst12 = (IReadOnlyList<string>)oa2; // Ok
    }
}

Přiřazení lst2 = oa1 generuje chybu v době kompilace, protože převod z object[] na IList<string> je explicitní převod, nikoli implicitní. Přetypování (IList<string>)oa1 způsobí vyvolání výjimky za běhu, protože oa1 odkazuje na a object[] nikoli na string[]. Přetypování (IList<string>)oa2 nezpůsobí výjimku, protože oa2 odkazuje na .string[]

end example

Kdykoli existuje implicitní nebo explicitní převod odkazu na S[] IList<T>, existuje rovněž explicitní převod odkazu a IList<T> jeho základní rozhraní (S[]§10.3.5).

Při implementaci IList<T>typu S[] pole mohou některé členy implementovaného rozhraní vyvolat výjimky. Přesné chování implementace rozhraní je nad rámec této specifikace.

17.3 Vytvoření pole

Maticové instance jsou vytvořeny pomocí array_creation_expressions (§12.8.16.5) nebo deklaracemi polí nebo místních proměnných, které obsahují array_initializer (§17.7). Instance pole lze také vytvořit implicitně jako součást vyhodnocení seznamu argumentů zahrnujícího pole parametrů (§15.6.2.4).

Při vytvoření instance pole se vytvoří pořadí a délka každé dimenze a zůstane konstantní po celou dobu životnosti instance. Jinými slovy, pořadí existující instance pole není možné změnit ani změnit jeho rozměry.

Instance pole je vždy typu pole. Typ System.Array je abstraktní typ, který nelze vytvořit instanci.

Prvky polí vytvořených array_creation_expressions jsou vždy inicializovány na výchozí hodnotu (§9.3).

Přístup k elementu Array 17.4

K prvkům pole se přistupuje pomocí výrazů element_access (§12.8.11.2) formuláře A[I₁, I₂, ..., Iₓ], kde A je výraz typu pole a každý Iₑ z nich je výraz typu int, uint, long, ulongnebo lze implicitně převést na jeden nebo více těchto typů. Výsledkem přístupu k prvku pole je proměnná, konkrétně prvek pole vybraný indexy.

Prvky pole lze vyčíslit pomocí foreach příkazu (§13.9.5).

17.5 Maticové členy

Každý typ pole dědí členy deklarované typem System.Array .

17.6 Kovariance matice

Pro všechny dva reference_type s a , pokud implicitní převod odkazu (§10.2.8) nebo explicitní převod odkazu (§10.3.5) existuje od A Btohoto typu do , pak stejný odkaz existuje také z typu A[R] matice na typ B[R]matice , kde R je některý z daných rank_specifier (ale stejný pro oba typy matice).BA Tato relace se označuje jako kovariance pole. Maticová kovariance zejména znamená, že hodnota typu A[R] pole může být ve skutečnosti odkazem na instanci typu B[R]pole za předpokladu, že implicitní převod odkazu existuje z B na A.

Z důvodu kovariance matice zahrnují přiřazení prvků matice typu odkazu kontrolu za běhu, která zajišťuje, že hodnota přiřazená prvku pole je skutečně povoleného typu (§12.21.2).

Příklad:

class Test
{
    static void Fill(object[] array, int index, int count, object value) 
    {
        for (int i = index; i < index + count; i++)
        {
            array[i] = value;
        }
    }

    static void Main() 
    {
        string[] strings = new string[100];
        Fill(strings, 0, 100, "Undefined");
        Fill(strings, 0, 10, null);
        Fill(strings, 90, 10, 0);
    }
}

Přiřazení metody array[i] Fill implicitně zahrnuje kontrolu za běhu, která zajišťuje, že value je null odkaz nebo odkaz na objekt typu, který je kompatibilní se skutečným typem arrayprvku . V Main, první dvě vyvolání Fill úspěchu, ale třetí vyvolání způsobí System.ArrayTypeMismatchException vyvolání při spuštění prvního přiřazení .array[i] K výjimce dochází, protože pole int nelze uložit do string pole.

end example

Kovariance pole se konkrétně nevztahuje na pole value_types. Například neexistuje žádný převod, který umožňuje int[] , aby bylo považováno object[]za .

17.7 Inicializátory polí

Inicializátory polí mohou být zadány v prohlášeních polí (§15.5), deklarace místních proměnných (§13.6.2) a výrazy vytváření matice (§12.8.16.5):

array_initializer
    : '{' variable_initializer_list? '}'
    | '{' variable_initializer_list ',' '}'
    ;

variable_initializer_list
    : variable_initializer (',' variable_initializer)*
    ;
    
variable_initializer
    : expression
    | array_initializer
    ;

Inicializátor pole se skládá z posloupnosti inicializátorů proměnných, uzavřených tokeny "{" a "}" a oddělené tokeny ",". Každý inicializátor proměnné je výraz nebo v případě multidimenzionálního pole inicializátoru vnořeného pole.

Kontext, ve kterém se používá inicializátor pole, určuje typ inicializovaného pole. Ve výrazu vytvoření pole předchází typ pole bezprostředně před inicializátorem nebo je odvozen z výrazů v inicializátoru pole. V deklaraci pole nebo proměnné je typ pole nebo proměnné deklarován. Při použití inicializátoru pole nebo proměnné v deklaraci pole nebo proměnné

int[] a = {0, 2, 4, 6, 8};

je to jednoduše zkratka pro ekvivalentní výraz vytvoření pole:

int[] a = new int[] {0, 2, 4, 6, 8};

Pro jednorozměrnou matici se inicializátor pole skládá z posloupnosti výrazů, z nichž každý má implicitní převod na typ prvku matice (§10.2). Výrazy inicializují prvky pole ve vzestupné pořadí, počínaje elementem na nulu indexu. Počet výrazů v inicializátoru pole určuje délku vytvářené instance pole.

Příklad: Inicializátor pole výše vytvoří int[] instanci o délce 5 a pak inicializuje instanci s následujícími hodnotami:

a[0] = 0; a[1] = 2; a[2] = 4; a[3] = 6; a[4] = 8;

end example

U multidimenzionálního pole musí inicializátor pole mít tolik úrovní vnoření, kolik má pole dimenzí. Vnější úroveň vnoření odpovídá levé dimenzi a nejvnitřnější úroveň vnoření odpovídá pravé dimenzi. Délka každé dimenze pole je určena počtem prvků na odpovídající úrovni vnoření v inicializátoru pole. Pro každý inicializátor vnořené pole musí být počet prvků stejný jako ostatní inicializátory pole na stejné úrovni.

Příklad: Příklad:

int[,] b = {{0, 1}, {2, 3}, {4, 5}, {6, 7}, {8, 9}};

vytvoří dvojrozměrné pole s délkou pěti pro levou dimenzi a délkou dvou dimenzí úplně vpravo:

int[,] b = new int[5, 2];

a pak inicializuje instanci pole následujícími hodnotami:

b[0, 0] = 0; b[0, 1] = 1;
b[1, 0] = 2; b[1, 1] = 3;
b[2, 0] = 4; b[2, 1] = 5;
b[3, 0] = 6; b[3, 1] = 7;
b[4, 0] = 8; b[4, 1] = 9;

end example

Pokud je k dispozici jiná dimenze než nejvíce vpravo s délkou nula, předpokládá se, že následující dimenze mají také nulovou délku.

Příklad:

int[,] c = {};

vytvoří dvojrozměrné pole s délkou nuly pro levou i úplně pravou dimenzi:

int[,] c = new int[0, 0];

end example

Pokud výraz vytvoření pole obsahuje explicitní délky dimenzí i inicializátor pole, musí být délky konstantními výrazy a počet prvků na každé úrovni vnoření se shoduje s odpovídající délkou dimenze.

Příklad: Tady je několik příkladů:

int i = 3;
int[] x = new int[3] {0, 1, 2}; // OK
int[] y = new int[i] {0, 1, 2}; // Error, i not a constant
int[] z = new int[3] {0, 1, 2, 3}; // Error, length/initializer mismatch

Inicializátor pro y výsledek chyby v době kompilace, protože výraz délky dimenze není konstanta a inicializátor pro z výsledky chyby v době kompilace, protože délka a počet prvků v inicializátoru nesouhlasí.

end example

Poznámka: C# umožňuje koncovou čárku na konci array_initializer. Tato syntaxe poskytuje flexibilitu při přidávání nebo odstraňování členů z tohoto seznamu a zjednodušuje generování takových seznamů. koncová poznámka