Белешка
Приступ овој страници захтева ауторизацију. Можете покушати да се пријавите или промените директоријуме.
Приступ овој страници захтева ауторизацију. Можете покушати да промените директоријуме.
Choose between anonymous types, System.Tuple<T1,T2>, and System.ValueTuple<T1,T2> based on usability, performance, and tradeoffs. ValueTuple provides a value type with the flexibility of anonymous types. This article explains when to choose each type.
Usability and functionality
With Language-Integrated Query (LINQ), you often project query results into anonymous types that hold a few selected properties from the source objects. The following example instantiates an array of DateTime objects and projects each object into an anonymous type with two properties.
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}");
}
Anonymous types are instantiated by using the new operator, and the property names and types are inferred from the declaration. If two or more anonymous object initializers in the same assembly specify a sequence of properties that are in the same order and that have the same names and types, the compiler treats the objects as instances of the same type. They share the same compiler-generated type information.
The previous C# snippet projects an anonymous type with two properties, much like the following compiler-generated C# class:
internal sealed class f__AnonymousType0
{
public string Formatted { get; }
public long Ticks { get; }
public f__AnonymousType0(string formatted, long ticks)
{
Formatted = formatted;
Ticks = ticks;
}
}
For more information, see anonymous types. The same functionality exists with tuples when projecting into LINQ queries, you can select properties into tuples. These tuples flow through the query, just as anonymous types would. Now consider the following example using the 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}");
}
With the System.Tuple<T1,T2>, the instance exposes numbered item properties, such as Item1, and Item2. These property names can make it more difficult to understand the intent of the property values, as the property name only provides the ordinal. Furthermore, the System.Tuple types are reference class types. The System.ValueTuple<T1,T2> however, is a value struct type. The following C# snippet, uses ValueTuple<string, long> to project into. In doing so, it assigns using a literal syntax.
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}");
}
For more information about tuples, see Tuple types (C# reference) or Tuples (Visual Basic).
The previous examples are all functionally equivalent, however, there are slight differences in their usability and their underlying implementations.
Tradeoffs
You might want to always use ValueTuple over Tuple, and anonymous types, but there are tradeoffs you should consider. The ValueTuple types are mutable, whereas Tuple are read-only. Anonymous types can be used in expression trees, while tuples cannot. The following table is an overview of some of the key differences.
Key differences
| Name | Access modifier | Type | Custom member name | Deconstruction support | Expression tree support |
|---|---|---|---|---|---|
| Anonymous types | internal |
class |
✔️ | ❌ | ✔️ |
| Tuple | public |
class |
❌ | ❌ | ✔️ |
| ValueTuple | public |
struct |
✔️ | ✔️ | ❌ |
Serialization
One important consideration when choosing a type, is whether or not it will need to be serialized. Serialization is the process of converting the state of an object into a form that can be persisted or transported. For more information, see serialization. When serialization is important, creating a class or struct is preferred over anonymous types or tuple types.
Performance
Performance between these types depends on the scenario. The major impact involves the tradeoff between allocations and copying. In most scenarios, the impact is small. When major impacts could arise, measurements should be taken to inform the decision.
Conclusion
As a developer choosing between tuples and anonymous types, there are several factors to consider. Generally speaking, if you're not working with expression trees, and you're comfortable with tuple syntax then choose ValueTuple as they provide a value type with the flexibility to name properties. If you're working with expression trees, and you'd prefer to name properties, choose anonymous types. Otherwise, use Tuple.