Typy řazené kolekce členů (referenční dokumentace jazyka C#)

Funkce řazených kolekcí členů poskytuje stručnou syntaxi pro seskupení více datových prvků ve zjednodušené datové struktuře. Následující příklad ukazuje, jak můžete deklarovat proměnnou řazené kolekce členů, inicializovat ji a přistupovat k jejím datovým členům:

(double, int) t1 = (4.5, 3);
Console.WriteLine($"Tuple with elements {t1.Item1} and {t1.Item2}.");
// Output:
// Tuple with elements 4.5 and 3.

(double Sum, int Count) t2 = (4.5, 3);
Console.WriteLine($"Sum of {t2.Count} elements is {t2.Sum}.");
// Output:
// Sum of 3 elements is 4.5.

Jak ukazuje předchozí příklad, pokud chcete definovat typ řazené kolekce členů, zadáte typy všech jeho datových členů a volitelně názvy polí. Metody typu řazené kolekce členů nemůžete definovat, ale můžete použít metody, které poskytuje .NET, jak ukazuje následující příklad:

(double, int) t = (4.5, 3);
Console.WriteLine(t.ToString());
Console.WriteLine($"Hash code of {t} is {t.GetHashCode()}.");
// Output:
// (4.5, 3)
// Hash code of (4.5, 3) is 718460086.

Typy řazené kolekce členů podporují operátory== rovnosti a !=. Další informace najdete v části Rovnosti řazené kolekce členů.

Typy řazené kolekce členů jsou typy hodnot. Prvky řazené kolekce členů jsou veřejná pole. Díky tomu jsou řazené typy hodnot řazené řazené kolekce členů.

Řazené kolekce členů můžete definovat libovolným velkým počtem prvků:

var t =
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26);
Console.WriteLine(t.Item26);  // output: 26

Případy použití řazených kolekcí členů

Jedním z nejběžnějších případů použití řazených kolekcí členů je návratový typ metody. To znamená, že místo definování out parametrů metody můžete metodu seskupit tak, aby výsledkem návratového typu řazené kolekce členů, jak ukazuje následující příklad:

int[] xs = [4, 7, 9];
var limits = FindMinMax(xs);
Console.WriteLine($"Limits of [{string.Join(" ", xs)}] are {limits.min} and {limits.max}");
// Output:
// Limits of [4 7 9] are 4 and 9

int[] ys = [-9, 0, 67, 100];
var (minimum, maximum) = FindMinMax(ys);
Console.WriteLine($"Limits of [{string.Join(" ", ys)}] are {minimum} and {maximum}");
// Output:
// Limits of [-9 0 67 100] are -9 and 100

(int min, int max) FindMinMax(int[] input)
{
    if (input is null || input.Length == 0)
    {
        throw new ArgumentException("Cannot find minimum and maximum of a null or empty array.");
    }

    // Initialize min to MaxValue so every value in the input
    // is less than this initial value.
    var min = int.MaxValue;
    // Initialize max to MinValue so every value in the input
    // is greater than this initial value.
    var max = int.MinValue;
    foreach (var i in input)
    {
        if (i < min)
        {
            min = i;
        }
        if (i > max)
        {
            max = i;
        }
    }
    return (min, max);
}

Jak ukazuje předchozí příklad, můžete s vrácenou instancí řazené kolekce členů pracovat přímo nebo ji dekonstruovat v samostatných proměnných.

Můžete také použít typy řazené kolekce členů místo anonymních typů, například v dotazech LINQ. Další informace naleznete v tématu Volba mezi anonymními typy a typy řazené kolekce členů.

Obvykle se používá řazené kolekce členů k seskupení volně souvisejících datových prvků. Ve veřejných rozhraních API zvažte definování třídy nebo typu struktury .

Názvy polí řazené kolekce členů

Názvy polí řazené kolekce členů explicitně zadáte ve výrazu inicializace řazené kolekce členů nebo v definici typu řazené kolekce členů, jak ukazuje následující příklad:

var t = (Sum: 4.5, Count: 3);
Console.WriteLine($"Sum of {t.Count} elements is {t.Sum}.");

(double Sum, int Count) d = (4.5, 3);
Console.WriteLine($"Sum of {d.Count} elements is {d.Sum}.");

Pokud nezadáte název pole, může být odvozen z názvu odpovídající proměnné ve výrazu inicializace řazené kolekce členů, jak ukazuje následující příklad:

var sum = 4.5;
var count = 3;
var t = (sum, count);
Console.WriteLine($"Sum of {t.count} elements is {t.sum}.");

Říká se tomu inicializátory projekce řazené kolekce členů. Název proměnné se neprojektuje na název pole řazené kolekce členů v následujících případech:

  • Jméno kandidáta je název člena typu řazené kolekce členů, Item3například , ToString, nebo Rest.
  • Název kandidáta je duplikát jiného názvu pole řazené kolekce členů, a to buď explicitně, nebo implicitně.

V předchozíchpřípadechch

Výchozí názvy polí řazené kolekce členů jsou Item1a Item3Item2tak dále. Výchozí název pole můžete použít vždy, i když je název pole zadán explicitně nebo odvozen, jak ukazuje následující příklad:

var a = 1;
var t = (a, b: 2, 3);
Console.WriteLine($"The 1st element is {t.Item1} (same as {t.a}).");
Console.WriteLine($"The 2nd element is {t.Item2} (same as {t.b}).");
Console.WriteLine($"The 3rd element is {t.Item3}.");
// Output:
// The 1st element is 1 (same as 1).
// The 2nd element is 2 (same as 2).
// The 3rd element is 3.

Přiřazování řazené kolekce členů a porovnávání rovnosti řazených kolekcí členů nebere v úvahu názvy polí.

V době kompilace nahradí kompilátor názvy jiných než výchozích polí odpovídajícími výchozími názvy. V důsledku toho explicitně zadané nebo odvozené názvy polí nejsou v době běhu k dispozici.

Tip

Povolte pravidlo stylu kódu .NET IDE0037 nastavit předvolbu pro odvozené nebo explicitní názvy polí řazené kolekce členů.

Počínaje jazykem C# 12 můžete zadat alias pro typ řazené kolekce členů pomocí direktivyusing. Následující příklad přidá global using alias pro typ řazené kolekce členů se dvěma celočíselnou hodnotou pro povolenou Min a Max hodnotu:

global using BandPass = (int Min, int Max);

Po deklarování aliasu BandPass můžete název použít jako alias pro tento typ řazené kolekce členů:

BandPass bracket = (40, 100);
Console.WriteLine($"The bandpass filter is {bracket.Min} to {bracket.Max}");

Alias nezavádí nový typ, ale vytvoří jenom synonymum pro existující typ. Dekonstrukci řazené kolekce členů deklarované pomocí aliasu BandPass můžete stejně jako u základního typu řazené kolekce členů:

(int a , int b) = bracket;
Console.WriteLine($"The bracket is {a} to {b}");

Stejně jako u přiřazení řazené kolekce členů nebo dekonstrukce nemusí názvy členů řazené kolekce členů odpovídat; typy.

Podobně lze druhý alias se stejnými typy arity a členy použít zaměnitelně s původním aliasem. Můžete deklarovat druhý alias:

using Range = (int Minimum, int Maximum);

Řazenou kolekci Range členů můžete přiřadit řazené BandPass kolekci členů. Stejně jako u všech přiřazení řazené kolekce členů se názvy polí nemusí shodovat, pouze typy arity.

Range r = bracket;
Console.WriteLine($"The range is {r.Minimum} to {r.Maximum}");

Alias pro typ řazené kolekce členů poskytuje více sémantických informací při použití řazených kolekcí členů. Nezavádí nový typ. Pokud chcete zajistit bezpečnost typů, měli byste místo toho deklarovat pozici record .

Přiřazení a dekonstrukce řazené kolekce členů

Jazyk C# podporuje přiřazení mezi typy řazené kolekce členů, které splňují obě následující podmínky:

  • Oba typy řazené kolekce členů mají stejný počet prvků.
  • pro každou pozici řazené kolekce členů je typ prvku řazené kolekce členů zprava stejný jako nebo implicitně konvertibilní na typ odpovídajícího prvku řazené kolekce členů na levé straně.

Hodnoty elementů řazené kolekce členů jsou přiřazeny podle pořadí prvků řazené kolekce členů. Názvy polí řazené kolekce členů se ignorují a nepřiřazují, jak ukazuje následující příklad:

(int, double) t1 = (17, 3.14);
(double First, double Second) t2 = (0.0, 1.0);
t2 = t1;
Console.WriteLine($"{nameof(t2)}: {t2.First} and {t2.Second}");
// Output:
// t2: 17 and 3.14

(double A, double B) t3 = (2.0, 3.0);
t3 = t2;
Console.WriteLine($"{nameof(t3)}: {t3.A} and {t3.B}");
// Output:
// t3: 17 and 3.14

Operátor = přiřazení můžete také použít k dekonstrukci instance řazené kolekce členů v samostatných proměnných. Můžete to udělat mnoha způsoby:

  • Pomocí klíčového var slova mimo závorky deklarujte implicitně zadané proměnné a nechte kompilátoru odvodit jejich typy:

    var t = ("post office", 3.6);
    var (destination, distance) = t;
    Console.WriteLine($"Distance to {destination} is {distance} kilometers.");
    // Output:
    // Distance to post office is 3.6 kilometers.
    
  • Explicitně deklarujte typ každé proměnné uvnitř závorek:

    var t = ("post office", 3.6);
    (string destination, double distance) = t;
    Console.WriteLine($"Distance to {destination} is {distance} kilometers.");
    // Output:
    // Distance to post office is 3.6 kilometers.
    
  • Deklarujte některé typy explicitně a jiné typy implicitně (s var) uvnitř závorek:

    var t = ("post office", 3.6);
    (var destination, double distance) = t;
    Console.WriteLine($"Distance to {destination} is {distance} kilometers.");
    // Output:
    // Distance to post office is 3.6 kilometers.
    
  • Použijte existující proměnné:

    var destination = string.Empty;
    var distance = 0.0;
    
    var t = ("post office", 3.6);
    (destination, distance) = t;
    Console.WriteLine($"Distance to {destination} is {distance} kilometers.");
    // Output:
    // Distance to post office is 3.6 kilometers.
    

Cíl dekonstrukčního výrazu může zahrnovat jak existující proměnné, tak proměnné deklarované v deklaraci dekonstrukce.

Dekonstrukci můžete také zkombinovat s porovnávání vzorů a zkontrolovat vlastnosti polí v řazené kolekci členů. Následující příklad prochází několik celých čísel a vytiskne ty, které jsou dělitelné 3. Dekonstruuje výsledek Int32.DivRem řazené kolekce členů a odpovídá hodnotě Remainder 0:

for (int i = 4; i < 20;  i++)
{
    if (Math.DivRem(i, 3) is ( Quotient: var q, Remainder: 0 ))
    {
        Console.WriteLine($"{i} is divisible by 3, with quotient {q}");
    }
}

Další informace o dekonstrukci řazených kolekcí členů a dalších typech naleznete v tématu Dekonstrukce řazených kolekcí členů a dalších typů.

Rovnost řazené kolekce členů

Typy řazené kolekce členů podporují operátory == a != operátory. Tyto operátory porovnávají členy levého operandu s odpovídajícími členy pravého operandu podle pořadí prvků řazené kolekce členů.

(int a, byte b) left = (5, 10);
(long a, int b) right = (5, 10);
Console.WriteLine(left == right);  // output: True
Console.WriteLine(left != right);  // output: False

var t1 = (A: 5, B: 10);
var t2 = (B: 5, A: 10);
Console.WriteLine(t1 == t2);  // output: True
Console.WriteLine(t1 != t2);  // output: False

Jak ukazuje předchozí příklad, == operace != nebere v úvahu názvy polí řazené kolekce členů.

Dvě řazené kolekce členů jsou srovnatelné, pokud jsou splněny obě následující podmínky:

  • Oba řazené kolekce členů mají stejný počet prvků. Například se nekompiluje, t1 != t2 pokud t1 a t2 má různý počet prvků.
  • Pro každou pozici řazené kolekce členů jsou odpovídající prvky z levé a pravé operandy řazené kolekce členů srovnatelné s == operátory a != operátory. Například se nekompiluje, (1, (2, 3)) == ((1, 2), 3) protože 1 není srovnatelný s (1, 2).

Operátory == porovnávají != řazené kolekce členů krátkým způsobem. To znamená, že operace se zastaví, jakmile splní dvojici nerovných prvků nebo dosáhne konce řazených kolekcí členů. Před jakýmkoli porovnáním se však vyhodnotí všechny prvky řazené kolekce členů, jak ukazuje následující příklad:

Console.WriteLine((Display(1), Display(2)) == (Display(3), Display(4)));

int Display(int s)
{
    Console.WriteLine(s);
    return s;
}
// Output:
// 1
// 2
// 3
// 4
// False

Řazené kolekce členů jako parametry

Obvykle refaktorujete metodu, která má out parametry do metody, která vrací řazenou kolekci členů. Existují však případy, kdy out parametr může být typu řazené kolekce členů. Následující příklad ukazuje, jak pracovat s řazenými kolekcemi členů jako out parametry:

var limitsLookup = new Dictionary<int, (int Min, int Max)>()
{
    [2] = (4, 10),
    [4] = (10, 20),
    [6] = (0, 23)
};

if (limitsLookup.TryGetValue(4, out (int Min, int Max) limits))
{
    Console.WriteLine($"Found limits: min is {limits.Min}, max is {limits.Max}");
}
// Output:
// Found limits: min is 10, max is 20

Řazené kolekce členů vs. System.Tuple

Řazené kolekce členů jazyka C#, které jsou založené na System.ValueTuple typech, se liší od řazených kolekcí členů, které jsou reprezentovány System.Tuple typy. Hlavní rozdíly jsou následující:

  • System.ValueTuple typy jsou hodnotové typy. System.Tuple typy jsou odkazové typy.
  • System.ValueTuple typy jsou proměnlivé. System.Tuple typy jsou neměnné.
  • Datové členy typů System.ValueTuple jsou pole. Datové členy typů System.Tuple jsou vlastnosti.

specifikace jazyka C#

Další informace naleznete v tématu:

Viz také