I'm surprised there isn't a question on this already. C# 7 added value tuples. I'm trying to figure out when I should adopt these features.
Take this dictionary for example uses Anonymous Type:
var changesTypeMapByEntityState = this.ChangeTracker.Entries()
.Where(x => (int)x.State > (int)EntityState.Unchanged)
.GroupBy(x => new { Type = x.Entity.GetType(), x.State })
.ToDictionary(x => x.Key, x => x.ToList());
Vs this Dictionary which uses Value Tuples
var changesTypeMapByEntityState = this.ChangeTracker.Entries()
.Where(x => (int)x.State > (int)EntityState.Unchanged)
.GroupBy(x => (Type: x.Entity.GetType(), x.State ))
.ToDictionary(x => x.Key, x => x.ToList());
Which one of these would perform better, and what are the benefits of using the new syntax vs the old?
The ValueTuple types are mutable, whereas Tuple are read-only. Anonymous types can be used in expression trees, while tuples cannot.
Tuple is a great option when you want to combine multiple values (can be different types) into one object without creating a custom class.
Tuple types are value types; tuple elements are public fields. That makes tuples mutable value types.
ValueTuple provides more flexibility for accessing the elements of the value tuples by using deconstruction and the _ keyword. But Tuple cannot provide the concept of deconstruction and the _ keyword. In ValueTuple the members such as item1 and item2 are fields. But in Tuple, they are properties.
In this situation, there's not much difference.
But in other situations value tuples can have a significant performance advantage. Because they are value types rather than reference types, a careful programmer can sometimes use them to avoid allocating new memory on the heap that must also be managed and collected. Additionally, value tuples are easier to share outside of the local scope, and so are legal in a number of situations where anonymous types are not.
That said, value types and reference types can also have different semantics, meaning you may have situations where a reference to anonymous type is much more appropriate, especially if you copy the reference around a lot.
Finally, it's not common for GC memory management to be the main performance driver of a program. The value tuple performance advantages aren't very likely to make a big enough difference to rush off and change all your old code, unless you have unlimited time to spend with a profiler tool to be sure it's a win. It's more worthwhile to be mindful of which choice produces clearer code or uses better semantics.
There's a really obvious case where you'd use a Value Tuple
instead of an anonymous objects, and that's when you need to return objects to the caller.
With the Value Tuple
you have a fast way to return any number of named properties, which is not very feasible with anonymous objects.
For example:
public (int Count, string Hello) GetDataTuple()
{
return (1, "world");
}
public object GetDataObject()
{
return new { Count = 1, Hello = "World" };
}
Then:
var dataTuple = GetDataTuple();
Console.WriteLine(dataTuple.Count); // valid
var dataObject = GetDataObject();
Console.WriteLine(dataOjbect.Hello); // invalid
This also applies, logically, to properties/fields in classes:
class Test
{
public (int Count, string Hello) DataTuple { get; set; } // valid
public 'A DataObject { get; set; } // obviously invalid
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With