【问题标题】:Anonymous type vs tuple in Linq query, performance considerationsLinq 查询中的匿名类型与元组,性能注意事项
【发布时间】: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

我们的业务规则类似于:

  • 如果ExemplarFriendNames 包含的条目在我们的exampleData 中不是另一个ExemplarName,则该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


【解决方案1】:

匿名类型值元组有一些非常细微的区别。

  • 平等
  • 存储 - 堆/堆栈
  • 参数命名
  • 表达式树
  • 语法 - 构造语法、解构等
  • 用法 - 如何将它们用作方法参数等

由于这个问题是关于中介使用的,值元组可能会因为 LINQ表达式树而被堆分配>ORMS 不在等式。然后除了相等和语法之外几乎没有区别,另外性能影响将相当不明显。所以答案真的归结为选择你最喜欢的。


其他资源

Choosing between anonymous and tuple types

权衡

您可能希望始终使用 ValueTuple 而不是 Tuple,并且是匿名的 类型,但您应该考虑一些权衡。值元组 类型是可变的,而 Tuple 是只读的。匿名类型可以是 用于表达式树,而元组不能。下表是 一些关键差异的概述。

主要区别

Name Access modifier Type Custom name Deconstruction Expression tree
Anonymous types internal class ✔️ ✔️
Tuple public class ✔️
ValueTuple public struct ✔️ ✔️

性能

这些类型之间的性能取决于场景。专业 影响涉及分配和复制之间的权衡。多数情况 情景,影响很小。当可能产生重大影响时, 应进行测量以告知决策。


进一步阅读

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多