Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
N-tice poskytují lehkou datovou strukturu pro více členů v jedné struktuře. Jsou upřednostňovanou volbou před anonymními typy. N-tice poskytují lepší výkon, podporují dekonstrukci a nabízejí flexibilnější syntaxi.
Anonymní typy poskytují pohodlný způsob zapouzdření sady vlastností jen pro čtení do jednoho objektu, aniž byste museli explicitně definovat typ jako první. Kompilátor vygeneruje název typu a není k dispozici na úrovni zdrojového kódu. Kompilátor odvodí typ každé vlastnosti. Anonymní typy používejte hlavně v případě, že potřebujete podporu stromu výrazů nebo při práci s kódem, který vyžaduje odkazové typy.
Řazené kolekce členů vs. anonymní typy
Řazené n-tice i anonymní typy umožňují vám seskupit více hodnot bez definování pojmenovaného typu. Nicméně, n-tice mají lepší jazykovou podporu a kompilují se do efektivnější datové struktury. Následující tabulka shrnuje klíčové rozdíly:
| Vlastnost | Anonymní typy | Tuply |
|---|---|---|
| Typ | Typ odkazu (class) |
Typ hodnoty (struct) |
| Performance | Přidělení haldy | Přidělení zásobníku (lepší výkon) |
| Mutability | Vlastnosti pouze pro čtení | Proměnlivá pole |
| Dekonstrukce | Není podporováno | Podporováno |
| Stromy výrazů | Podporováno | Není podporováno |
| Modifikátor přístupu | internal |
public |
| Jména členů | Povinné nebo vyvozené | Volitelné (s výchozími názvy jako Item1, Item2) |
Kdy použít n-tice
Použijte n-tice, když:
- Potřebujete lepší výkon díky alokaci zásobníku.
- Hodnoty chcete dekonstruovat do samostatných proměnných.
- Vracíte z metody více hodnot.
- Podporu stromu výrazů nepotřebujete.
Následující příklad ukazuje, jak řazené kolekce členů poskytují podobné funkce anonymním typům s čistější syntaxí:
// Tuple with named elements.
var tupleProduct = (Name: "Widget", Price: 19.99M);
Console.WriteLine($"Tuple: {tupleProduct.Name} costs ${tupleProduct.Price}");
// Equivalent example using anonymous types.
var anonymousProduct = new { Name = "Widget", Price = 19.99M };
Console.WriteLine($"Anonymous: {anonymousProduct.Name} costs ${anonymousProduct.Price}");
Dekonstrukce n-tice
Řazenou kolekci členů můžete dekonstruovat do samostatných proměnných, což poskytuje pohodlný způsob, jak pracovat s jednotlivými prvky řazené kolekce členů. Jazyk C# podporuje několik způsobů dekonstruování n-tic:
static (string Name, int Age, string City) GetPersonInfo()
{
return ("Alice", 30, "Seattle");
}
// Deconstruct using var for all variables
var (name, age, city) = GetPersonInfo();
Console.WriteLine($"{name} is {age} years old and lives in {city}");
// Output: Alice is 30 years old and lives in Seattle
// Deconstruct with explicit types
(string personName, int personAge, string personCity) = GetPersonInfo();
Console.WriteLine($"{personName}, {personAge}, {personCity}");
// Deconstruct into existing variables
string existingName;
int existingAge;
string existingCity;
(existingName, existingAge, existingCity) = GetPersonInfo();
// Deconstruct and discard unwanted values using the discard pattern (_)
var (name2, _, city2) = GetPersonInfo();
Console.WriteLine($"{name2} lives in {city2}");
// Output: Alice lives in Seattle
Dekonstrukce je užitečná ve scénářích smyček a porovnávání vzorů:
var people = new List<(string Name, int Age)>
{
("Bob", 25),
("Carol", 35),
("Dave", 40)
};
foreach (var (personName2, personAge2) in people)
{
Console.WriteLine($"{personName2} is {personAge2} years old");
}
n-tice jako návratový typ metody
Běžným případem použití tuplů je návratový typ metody. Místo definování out parametrů můžete seskupit výsledky metody v řazené kolekci členů. Anonymní typ nelze vrátit z metody, protože nemá název a návratový typ nelze deklarovat.
Následující příklad ukazuje použití n-tic s vyhledáním ve slovníku k vrácení konfiguračních rozsahů.
var configLookup = new Dictionary<int, (int Min, int Max)>()
{
[2] = (4, 10),
[4] = (10, 20),
[6] = (0, 23)
};
if (configLookup.TryGetValue(4, out (int Min, int Max) range))
{
Console.WriteLine($"Found range: min is {range.Min}, max is {range.Max}");
}
// Output: Found range: min is 10, max is 20
Tento vzor je užitečný při práci s metodami, které potřebují vrátit ukazatel úspěchu i více hodnot výsledků. N-tice umožňuje používat pojmenovaná pole, jako jsou Min a Max, namísto obecných názvů, jako jsou Item1 a Item2, což činí kód čitelnější a lépe dokumentovaný.
Kdy použít anonymní typy
Anonymní typy použijte, když:
- Pracujete se stromy výrazů (například v některých poskytovatelích Microsoft Language-Integrated Query (LINQ)).
- Objekt potřebujete, aby byl odkazovým typem.
Nejběžnějším scénářem je inicializace anonymního typu s vlastnostmi z jiného typu. V následujícím příkladu předpokládejme, že třída existuje s názvem Product. Třída Product obsahuje Color a Price vlastnosti společně s dalšími vlastnostmi, které vás nezajímají:
class Product
{
public string? Color { get; init; }
public decimal Price { get; init; }
public string? Name { get; init; }
public string? Category { get; init; }
public string? Size { get; init; }
}
Deklarace anonymního typu začíná new operátorem společně s inicializátorem objektu. Deklarace inicializuje nový typ, který používá pouze dvě vlastnosti z Product. Anonymní typy se obvykle používají v select klauzuli výrazu dotazu k vrácení menšího množství dat. Další informace odotazch
Pokud nezadáte názvy členů v anonymním typu, kompilátor dává členům anonymního typu stejný název jako vlastnost použitá k inicializaci. Zadáte název vlastnosti, která se inicializuje pomocí výrazu, jak je znázorněno v předchozím příkladu.
V následujícím příkladu jsou názvy vlastností anonymního typu Color a Price. Instance jsou položky z products kolekce Product typů:
var productQuery =
from prod in products
select new { prod.Color, prod.Price };
foreach (var v in productQuery)
{
Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
}
Inicializátory projekce s anonymními typy
Anonymní typy podporují inicializátory projekce, které umožňují použít místní proměnné nebo parametry přímo bez explicitního zadání názvu člena. Kompilátor odvodí názvy členů z názvů proměnných. Následující příklad ukazuje tuto zjednodušenou syntaxi:
// Explicit member names.
var personExplicit = new { FirstName = "Kyle", LastName = "Mit" };
// Projection initializers (inferred member names).
var firstName = "Kyle";
var lastName = "Mit";
var personInferred = new { firstName, lastName };
// Both create equivalent anonymous types with the same property names.
Console.WriteLine($"Explicit: {personExplicit.FirstName} {personExplicit.LastName}");
Console.WriteLine($"Inferred: {personInferred.firstName} {personInferred.lastName}");
Tato zjednodušená syntaxe je užitečná při vytváření anonymních typů s mnoha vlastnostmi:
var title = "Software Engineer";
var department = "Engineering";
var salary = 75000;
// Using projection initializers.
var employee = new { title, department, salary };
// Equivalent to explicit syntax:
// var employee = new { title = title, department = department, salary = salary };
Console.WriteLine($"Title: {employee.title}, Department: {employee.department}, Salary: {employee.salary}");
Název člena není odvozen v následujících případech:
- Název kandidáta se shoduje s jiným členem vlastnosti ve stejném anonymním typu, a to buď explicitně, nebo implicitně.
- Název kandidáta není platný identifikátor (například obsahuje mezery nebo speciální znaky).
V těchto případech musíte explicitně zadat název člena.
Návod
Pravidlo stylu .NET můžete použít IDE0037 k vynucení, jestli jsou upřednostňované odvozené nebo explicitní názvy členů.
Pole můžete také definovat pomocí objektu jiného typu: třídy, struktury nebo dokonce jiného anonymního typu. K tomu použijte proměnnou, která obsahuje tento objekt. Následující příklad ukazuje dva anonymní typy, které používají již definované uživatelem definované typy. V obou případech product pole v anonymních typech shipment a shipmentWithBonus je typu Product a obsahuje výchozí hodnoty každého pole. Pole bonus je anonymního typu vytvořeného kompilátorem.
var product = new Product();
var bonus = new { note = "You won!" };
var shipment = new { address = "Nowhere St.", product };
var shipmentWithBonus = new { address = "Somewhere St.", product, bonus };
Při inicializaci proměnné pomocí anonymního typu obvykle deklarujete proměnnou jako implicitně zatypovanou místní proměnnou pomocí proměnné var. V deklaraci proměnné nelze zadat název typu, protože k základnímu názvu anonymního typu má přístup pouze kompilátor. Další informaceochch var
Pole anonymně zadaných elementů můžete vytvořit kombinací implicitně zadané místní proměnné a implicitně zadaného pole, jak je znázorněno v následujícím příkladu.
var anonArray = new[] { new { name = "apple", diam = 4 }, new { name = "grape", diam = 1 }};
Anonymní typy jsou class typy, které jsou odvozeny přímo z object, a nemůžete je přetypovat na žádný typ s výjimkou object. Kompilátor poskytuje název pro každý anonymní typ, i když k němu aplikace nemá přístup. Z pohledu modulu CLR (Common Language Runtime) se anonymní typ neliší od jiného typu odkazu.
Pokud dva nebo více anonymních inicializátorů objektů v sestavení určují posloupnost vlastností, které jsou ve stejném pořadí a mají stejné názvy a typy, kompilátor zachází s objekty jako s instancemi stejného typu. Sdílejí stejné informace o typu generovaném kompilátorem.
Anonymní typy podporují nedestruktivní mutování ve formě výrazů. Tato funkce umožňuje vytvořit novou instanci anonymního typu, kde jedna nebo více vlastností má nové hodnoty:
var apple = new { Item = "apples", Price = 1.35 };
var onSale = apple with { Price = 0.79 };
Console.WriteLine(apple);
Console.WriteLine(onSale);
Nelze deklarovat pole, vlastnost, událost nebo návratový typ metody jako anonymní typ. Podobně nemůžete deklarovat formální parametr metody, vlastnosti, konstruktoru nebo indexeru jako anonymní typ. Chcete-li předat anonymní typ nebo kolekci, která obsahuje anonymní typy, jako argument metody, můžete deklarovat parametr jako typ object. Použití object pro anonymní typy však porazí účel silného psaní. Pokud je nutné uložit výsledky dotazu nebo je předat mimo hranice metody, zvažte použití obyčejné pojmenované struktury nebo třídy namísto anonymního typu.
Vzhledem k tomu, že Equals anonymní typy a GetHashCode metody jsou definovány z hlediska Equals a GetHashCode metod vlastností, jsou dvě instance stejného anonymního typu stejné, pouze pokud jsou všechny jejich vlastnosti stejné.
Poznámka:
Úroveň přístupnosti anonymního typu je internal. Proto dva anonymní typy definované v různých sestaveních nejsou stejného typu.
Proto se instance anonymních typů nemohou navzájem rovnat, pokud jsou definovány v různých sestaveních, i když mají všechny jejich vlastnosti stejné.
Anonymní typy přepíší metodu ToString , zřetězení názvu a ToString výstupu každé vlastnosti obklopené složenými závorkami.
var v = new { Title = "Hello", Age = 24 };
Console.WriteLine(v.ToString()); // "{ Title = Hello, Age = 24 }"