Typy řazené kolekce členů (Referenční příručka jazyka C#)

Funkce řazených kolekce členů, která je dostupná v jazyce C# 7.0 a novějším, poskytuje stručnou syntaxi pro seskupení více datových prvků do zjednodušené datové struktury. Následující příklad ukazuje, jak deklarovat proměnnou řazené kolekce členů, inicializovat ji a získat přístup 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, při definování typu řazené kolekce členů určíte typy všech datových členů a volitelně názvy polí. Metody nelze definovat v typu řazené kolekce členů, ale můžete použít metody poskytované rozhraním .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.

Počínaje jazykem C# 7.3 podporují typy řazené kolekce členů operátory rovnosti a == != . Další informace najdete v části Rovnost řazené kolekce členů.

Typy řazené kolekce členů jsou hodnotové typy; Prvky řazené kolekce členů jsou veřejná pole. Díky tomu jsou typy hodnot řazených kolekce členů měnné.

Poznámka

Funkce řazených kolekce členů vyžaduje typ a související obecné typy (například ), které jsou k dispozici v System.ValueTuple System.ValueTuple<T1,T2> .NET Core a .NET Framework 4.7 a novější. Pokud chcete použít řazené kolekce členů v projektu, .NET Framework 4.6.2 nebo starší, přidejte do projektu System.ValueTuple balíček NuGet.

Řazené kolekce členů můžete definovat s 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 kolekce členů

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

var xs = new[] { 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

var ys = new[] { -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.");
    }

    var min = int.MaxValue;
    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ísto anonymních typů můžete použít také typy řazené kolekce členů. například v dotazech LINQ. Další informace najdete v tématu Volba mezi anonymními typy a typy řazené kolekce členů.

Obvykle používáte řazené kolekce členů k seskupení volně souvisejících datových prvků. To je obvykle užitečné v rámci privátních a interních nástrojů. V případě veřejného rozhraní API zvažte definování třídy nebo typu struktury .

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

Můžete explicitně zadat názvy polí řazené kolekce členů buď v inicializačním výrazu ř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}.");

Počínaje jazykem C# 7,1, pokud nezadáte název pole, může být odvozen z názvu odpovídající proměnné v inicializačním výrazu ř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}.");

Označuje se jako Inicializátory řazené kolekce členů. Název proměnné není v následujících případech promítnut do pole řazené kolekce členů:

  • Kandidátský název je název členu typu řazené kolekce členů, například, Item3 , ToString nebo Rest .
  • Název kandidáta je duplikátem jiného názvu pole řazené kolekce členů, ať už explicitního, nebo implicitního.

V těchto případech buď explicitně zadáte název pole, nebo přístup k poli s jeho výchozím názvem.

Výchozí názvy polí řazené kolekce členů Item1 jsou Item2 , Item3 a tak dále. Můžete vždy použít výchozí název pole, a to i v případě, že 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řazení řazené kolekce členů a porovnání rovnosti řazené kolekce členů nevezmou názvy polí v účtu.

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

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

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

  • Oba typy řazené kolekce členů mají stejný počet elementů.
  • u každé pozice řazené kolekce členů je typ prvku řazené kolekce členů stejný jako nebo implicitně převoditelné na typ odpovídajícího elementu řazené kolekce členů na levé straně.

Hodnoty elementů řazené kolekce členů jsou přiřazeny za pořadím 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

Pomocí operátoru přiřazení můžete také = dekonstruovat instanci řazené kolekce členů v samostatných proměnných. Můžete to provést jedním z následujících způsobů:

  • Explicitně deklarujte typ každé proměnné v závorkách:

    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.
    
  • Pomocí klíčového slova mimo závorky deklarujte implicitně typované proměnné a nechte kompilátor var 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.
    
  • Použití existujících proměnných:

    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.
    

Další informace o dekonstrukci řazených kolekce členů a dalších typů najdete v tématu Dekonstrukce řazenýchkolekce členů a dalších typů .

Rovnost řazené kolekce členů

Počínaje jazykem C# 7.3 podporují typy řazené kolekce členů == operátory != a . Tyto operátory porovnávají členy levého operandu s odpovídajícími členy pravého operandu za pořadím 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 a nezohlední 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 t1 != t2 nezkompiluje, pokud t1 a mají jiný počet t2 prvků.
  • Pro každou pozici řazené kolekce členů jsou odpovídající prvky z operandů řazené kolekce členů vlevo a vpravo srovnatelné s == != operátory a . Například se (1, (2, 3)) == ((1, 2), 3) nezkompiluje, protože 1 není srovnatelný s (1, 2) .

Operátory == != a porovnávají řazené kolekce členů zkráceně. To znamená, že operace se zastaví, jakmile splňuje dvojici nerovných prvků nebo dosáhne konce řazených kolekce členů. Před 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 výstupní parametry

Obvykle refaktorujte metodu, která má out parametry do metody, která vrací řazenou kolekci členů. Existují však případy, ve kterých 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 zálohovány System.ValueTuple typy, se liší od řazených kolekcí členů, které jsou zastoupeny System.Tuple typy. Hlavní rozdíly jsou následující:

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

specifikace jazyka C#

Další informace najdete v těchto poznámkách k návrhu funkcí:

Viz také