Kiezen tussen anonieme typen en tuples
Als u het juiste type kiest, moet u rekening houden met de bruikbaarheid, prestaties en afwegingen ten opzichte van andere typen. Anonieme typen zijn beschikbaar sinds C# 3.0, terwijl algemene System.Tuple<T1,T2> typen zijn geïntroduceerd met .NET Framework 4.0. Sindsdien zijn nieuwe opties geïntroduceerd met taalniveauondersteuning, zoals System.ValueTuple<T1,T2> - die zoals de naam al aangeeft , een waardetype bieden met de flexibiliteit van anonieme typen. In dit artikel leert u wanneer u het ene type boven het andere type kunt kiezen.
Bruikbaarheid en functionaliteit
Anonieme typen zijn geïntroduceerd in C# 3.0 met LINQ-expressies (Language-Integrated Query). Met LINQ projecteren ontwikkelaars vaak resultaten van query's in anonieme typen die enkele geselecteerde eigenschappen bevatten van de objecten waarmee ze werken. Bekijk het volgende voorbeeld, waarmee een matrix met DateTime objecten wordt geïnstitueert en ze worden herhaald die projecteren in een anoniem type met twee eigenschappen.
var dates = new[]
{
DateTime.UtcNow.AddHours(-1),
DateTime.UtcNow,
DateTime.UtcNow.AddHours(1),
};
foreach (var anonymous in
dates.Select(
date => new { Formatted = $"{date:MMM dd, yyyy hh:mm zzz}", date.Ticks }))
{
Console.WriteLine($"Ticks: {anonymous.Ticks}, formatted: {anonymous.Formatted}");
}
Anonieme typen worden geïnstantieerd met behulp van de new
operator en de eigenschapsnamen en -typen worden afgeleid uit de declaratie. Als twee of meer anonieme object initializers in dezelfde assembly een reeks eigenschappen opgeven die zich in dezelfde volgorde bevinden en dezelfde namen en typen hebben, behandelt de compiler de objecten als exemplaren van hetzelfde type. Ze delen dezelfde door compiler gegenereerde typegegevens.
Het vorige C#-fragment projecteert een anoniem type met twee eigenschappen, vergelijkbaar met de volgende door de compiler gegenereerde C#-klasse:
internal sealed class f__AnonymousType0
{
public string Formatted { get; }
public long Ticks { get; }
public f__AnonymousType0(string formatted, long ticks)
{
Formatted = formatted;
Ticks = ticks;
}
}
Zie anonieme typen voor meer informatie. Dezelfde functionaliteit bestaat met tuples bij het projecteren in LINQ-query's. U kunt eigenschappen selecteren in tuples. Deze tuples stromen door de query, net zoals anonieme typen dat zouden doen. Bekijk nu het volgende voorbeeld met behulp van de System.Tuple<string, long>
.
var dates = new[]
{
DateTime.UtcNow.AddHours(-1),
DateTime.UtcNow,
DateTime.UtcNow.AddHours(1),
};
foreach (var tuple in
dates.Select(
date => new Tuple<string, long>($"{date:MMM dd, yyyy hh:mm zzz}", date.Ticks)))
{
Console.WriteLine($"Ticks: {tuple.Item2}, formatted: {tuple.Item1}");
}
Met de System.Tuple<T1,T2>instantie worden genummerde itemeigenschappen weergegeven, zoals Item1
, en Item2
. Deze eigenschapsnamen kunnen het lastiger maken om de intentie van de eigenschapswaarden te begrijpen, omdat de eigenschapsnaam alleen de rangschikt. Bovendien zijn de System.Tuple
typen referentietypen class
. Het System.ValueTuple<T1,T2> is echter een waardetype struct
. Het volgende C#-fragment wordt gebruikt ValueTuple<string, long>
om in te projecteren. Hierbij wordt een letterlijke syntaxis toegewezen.
var dates = new[]
{
DateTime.UtcNow.AddHours(-1),
DateTime.UtcNow,
DateTime.UtcNow.AddHours(1),
};
foreach (var (formatted, ticks) in
dates.Select(
date => (Formatted: $"{date:MMM dd, yyyy at hh:mm zzz}", date.Ticks)))
{
Console.WriteLine($"Ticks: {ticks}, formatted: {formatted}");
}
Zie Tuple-typen (C#-verwijzing) of Tuples (Visual Basic) voor meer informatie over tuples.
De vorige voorbeelden zijn allemaal functioneel gelijkwaardig, maar er zijn kleine verschillen in hun bruikbaarheid en de onderliggende implementaties.
Compromissen
Mogelijk wilt u altijd gebruik Tuplemaken ValueTuple van en anonieme typen, maar er zijn compromissen die u moet overwegen. De ValueTuple typen zijn veranderlijk, terwijl Tuple ze alleen-lezen zijn. Anonieme typen kunnen worden gebruikt in expressiestructuren, terwijl tuples dat niet kunnen. De volgende tabel is een overzicht van enkele van de belangrijkste verschillen.
Belangrijke verschillen
Naam | Wijzigingsfunctie voor toegang | Type | Aangepaste lidnaam | Ondersteuning voor de deconstructie | Ondersteuning voor expressiestructuur |
---|---|---|---|---|---|
Anonieme typen | internal |
class |
✔️ | ❌ | ✔️ |
Tuple | public |
class |
❌ | ❌ | ✔️ |
ValueTuple | public |
struct |
✔️ | ✔️ | ❌ |
Serialization
Een belangrijke overweging bij het kiezen van een type, is of het wel of niet moet worden geserialiseerd. Serialisatie is het proces van het converteren van de status van een object naar een formulier dat kan worden bewaard of vervoerd. Zie serialisatie voor meer informatie. Wanneer serialisatie belangrijk is, wordt het maken van een class
of struct
de voorkeur gegeven aan anonieme typen of tupletypen.
Prestaties
De prestaties tussen deze typen zijn afhankelijk van het scenario. De belangrijkste gevolgen zijn de afweging tussen toewijzingen en kopiëren. In de meeste scenario's is de impact klein. Wanneer er grote gevolgen kunnen ontstaan, moeten metingen worden genomen om de beslissing te informeren.
Conclusie
Als ontwikkelaar die kiest tussen tuples en anonieme typen, zijn er verschillende factoren waarmee u rekening moet houden. Over het algemeen geldt dat als u niet met expressiestructuren werkt en u vertrouwd bent met de tuplesyntaxis, dan kiest ValueTuple u omdat deze een waardetype bieden met de flexibiliteit om eigenschappen een naam te geven. Als u met expressiestructuren werkt en u liever eigenschappen wilt noemen, kiest u anonieme typen. Gebruik anders Tuple.