我很惊讶这已经没有问题了.C#7增加了值元组.我想知道什么时候应该采用这些功能.
以此字典为例使用匿名类型:
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());
Run Code Online (Sandbox Code Playgroud)
这个使用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());
Run Code Online (Sandbox Code Playgroud)
其中哪一个会表现得更好,使用新语法与旧语法有什么好处?
有一个非常明显的例子,你使用的Value Tuple是一个匿名对象,而当你需要将对象返回给调用者时.
使用Value Tuple您可以快速返回任意数量的命名属性,这对于匿名对象来说是不可行的.
例如:
public (int Count, string Hello) GetDataTuple()
{
return (1, "world");
}
public object GetDataObject()
{
return new { Count = 1, Hello = "World" };
}
Run Code Online (Sandbox Code Playgroud)
然后:
var dataTuple = GetDataTuple();
Console.WriteLine(dataTuple.Count); // valid
var dataObject = GetDataObject();
Console.WriteLine(dataOjbect.Hello); // invalid
Run Code Online (Sandbox Code Playgroud)
这在逻辑上也适用于类中的属性/字段:
class Test
{
public (int Count, string Hello) DataTuple { get; set; } // valid
public 'A DataObject { get; set; } // obviously invalid
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,差别不大。
但是在其他情况下,值元组可以具有显着的性能优势。因为它们是值类型而不是引用类型,所以谨慎的程序员有时可以使用它们来避免在必须同时管理和收集的堆上分配新的内存。此外,值元组在本地范围之外更易于共享,因此在许多不使用匿名类型的情况下也是合法的。
也就是说,值类型和引用类型也可以具有不同的语义,这意味着您可能会遇到对匿名类型的引用更为合适的情况,尤其是在您大量复制引用的情况下。
最后,GC内存管理成为程序的主要性能驱动因素并不常见。价值元组的性能优势不太可能产生足够大的差异来冲销并更改所有旧代码,除非您有无限时间花在探查器工具上以确保成功。牢记哪种选择会产生更清晰的代码或使用更好的语义是更值得的。