【发布时间】:2021-09-24 01:21:29
【问题描述】:
这个问题专门针对内存数据,与查询翻译框架无关(例如,与实体框架以及它如何能够和不能转录某些 Linq 查询无关)。
假设我们有一个 IEnumerable 包含类型:
class Exemplar
{
public Guid UniqueId { get; set; }
public string Name { get; set; }
public string[] FriendNames { get; set; }
}
var exampleData = new List<Exemplar>(); // pretend I'm populated
我们的业务规则类似于:
- 如果
Exemplar的FriendNames包含的条目在我们的exampleData中不是另一个Exemplar的Name,则该Exemplar无效 - 如果发现无效的
Exemplar,写出它是UniqueId,它的无效FriendNames
我习惯于编写使用匿名类型作为链中中间结构的 Linq 查询。例如:
var invalidExemplars =
exampleData
.Select(x =>
new
{
Id = x.UniqueId,
InvalidNames = x.FriendNames.Where(n => exampleData.All(d => d.Name != n)).ToArray()
})
.Where(x => x.InvalidNames.Any());
// added for completion, maybe irrelevant to the question
if (invalidExemplars.Any())
{
Console.WriteLine(string.Join(Environment.NewLine, invalidExemplars.Select(x => $"{x.Id}: [{ string.Join(",", x.InvalidNames)}]")));
}
但现在在 C# 7 中,我们可以使用新的元组简写代替匿名类型:
var invalidExemplars =
exampleData
.Select(x =>
(
Id: x.UniqueId,
InvalidNames: x.FriendNames.Where(n => exampleData.All(d => d.Name != n)).ToArray()
))
.Where(x => x.InvalidNames.Any());
我的问题是中间匿名类型与中间元组之间是否存在任何性能差异,如果有,它们是什么?
是否有任何理由(除了个人偏好)选择一个而不是另一个作为中介?
【问题讨论】:
-
匿名类型是分配,但是orms一般可以接受,value tuple是值类型,一般是栈分配的,orms不支持。但是,无需问我们哪个性能更高,比赛你的马
-
@TheGeneral 是的,如顶部所述,问题与其中任何一个如何与查询转录框架交互无关。你是对的,我可以“赛马”,并且根据一天、外部性能负载以及我对可能使用其中一种或另一种的各种方式的全面覆盖,我可能会得到不同的结果。我希望得到关于 .Net 如何在这种中间上下文中处理它们以及每种方法将如何影响性能的明智答案。
-
您想要一个明智的答案的原因,就是您需要赛马的确切原因。 ericlippert.com/2012/12/17/performance-rant
-
@TheGeneral 希望我没有在我的问题中暗示我对“更快”感兴趣。我对性能感兴趣,例如 “使用 X 会将数据放在堆栈上,而 Y 将使用堆,考虑到中间使用情况,最好使用 X/Y,因为堆栈/堆 GC 更有效” 可能是此处有效答案的部分。如果可以减轻您的顾虑,我可以从问题中删除所有对“性能”的提及?
-
匿名类型和值元组有一些非常细微的区别,这与相等、存储、参数命名以及如何将它们传递给其他方法有关。因为这是中介,值类型可能会因为 LINQ 而被堆分配,并且表达式树和 orms 不在等式中,几乎没有区别,但是可能会有微妙且相当不明显的性能差异。所以答案真的归结为选择你最喜欢的。
标签: c# linq tuples anonymous-types