【问题标题】:When is it better to use a Tuple versus a KeyValuePair?什么时候使用 Tuple 和 KeyValuePair 比较好?
【发布时间】:2013-10-31 14:12:40
【问题描述】:

每当我有一对相关的数据时,我通常使用KeyValuePair<TKey,TValue> 类型,即一个是另一个的关键。如果数据不相关,那么 Tuple<T1,T2> 类型更有意义,我会采用。

现在我刚刚阅读了this article,了解为什么通常避免使用KeyValuePair<TKey,TValue> 而更喜欢Tuple<T1,T2>。主要论点是Tuple<T1,T2> 的性能优势。

在性能方面,KVP 是否比Tuple<T1,T2> 更好?

【问题讨论】:

  • KeyValuePair 是键和值,Tuple<T1,T2> 只是一对 相等 值。你也可以问:“如果我可以使用Dictionary<A,B>,我为什么要使用List<Class>”。
  • 对,但在这种情况下,您可以使用键来查找数据。这意味着什么。在这种情况下,名称只是语义,它们(对处理器)没有任何意义。
  • 元组不是一对相等的值,而是一些相等的类型。也许这被视为吹毛求疵,但例如C 确实具有用于相等值的不同表示的联合构造。 :)

标签: .net semantics


【解决方案1】:

嗯,这个类型可能被认为命名不当,例如。命名的 KeyValuePair 应该代表一个键和一个值。如果您的两个对象不是真正的键和值,只是两件事怎么办?如果我看到一个类型为KeyValuePair<TKey, TValue> 的方法或属性,我希望 KVP 的值是键和值。这实际上只是传达意图并在未来向自己或其他团队成员明确表达的问题。元组不表示那种关联。

元组还可以更轻松地添加另一个值,使其成为 3 元组(或三元组,但你想怎么称呼它)。一些 .NET 语言,如 F#、have special syntax 也围绕元组。

从实现的角度来看,Tuple 做了很多 KeyValuePair 没有做的事情。元组具有可比性,它们实现了IComparableIStructuralEquatable 接口,因此比较两个元组更容易。

【讨论】:

  • 我发现你可以将 KeyValuePairs 放入字典但那时永远不会得到结果的艰难方法。
  • 此外,新的 C# 7.0 支持新的、更简单的元组语法,使它们比 KeyValuePairs 更容易使用。 visualstudiomagazine.com/articles/2017/01/01/…
  • 此外,在元组中命名参数的能力使消费者更容易理解它们应该用于什么。在像 KVP 这样的泛型中,这真的是任何人的猜测——除非它在某处专门记录——密钥应该“是”什么——即不是它的类型,而是它是什么真实世界的东西,比如设置名称、社交安全号码等
【解决方案2】:

KeyValuePair 是结构,Tuple 是一个类。

这是影响对象如何通过引用或值复制的主要区别。

因此 Tuple<T1,T2> 在 32 位操作系统中传递时只使用“4byte”,而 KeyValuePair<K,V> 需要更多基于“K 和 V”

无论如何比较 Tuple 和 KeyValuePair 不是一个好主意(对我来说没有意义),因为两者的用途不同。

【讨论】:

  • 它们如何服务于不同的目的?请您详细说明一下。
  • @YakRangi keyvaluepair 旨在用作字典中键和值的容器,否则,它没有任何作用。另一方面,元组可用于将任意相关的成员存储在一起。同样使用元组,您可以存储多个成员的组合,而不仅仅是 2。
  • @SriramSakthivel 这意味着,OP 问题的答案是:除非您正在浏览字典,否则不要使用 KVP。
【解决方案3】:

尽管存在语义,但在您同时考虑这两个选项时,性能可能是一个重要的考虑因素。如前所述,KeyValuePair 是值类型(结构),而Tuple<> 是引用类型(类)。因此KeyValuePair分配在栈上,Tuple<>分配在堆上,最优选择通常由Stack vs. Heap Memory Allocation的经典参数决定。简而言之,堆栈空间是有限的,但通常访问速度非常快。堆内存要大得多,但速度有点慢。

如果键和值类型都是原始类型(intbooldouble 等值类型)或小尺寸结构,KeyValuePair<T1, T2> 可能是更好的选择。使用堆栈上的原始类型,分配和释放速度非常快。 这确实会影响性能,尤其是作为递归方法调用的参数。

另一方面,如果T1T2 是引用类型(如类),Tuple<T1, T2> 可能是更好的选择。包含指向引用类型(作为键或值类型)的指针的 KeyValuePair 有点违背目的,因为无论如何都需要在堆上查找对象。

这是我在网上找到的基准:Tuple vs. KeyValuePair。这个基准测试的唯一问题是他们测试了KeyValuePair<string, string>Tuple<string, string>string 类型在 .NET 中是一种不寻常且特殊的类型,因为它可以像值类型和/或引用类型一样表现取决于执行上下文。我相信KeyValuePair<int, int> 将是对抗Tuple<int, int> 的明显赢家。然而,即使存在缺陷,结果也表明性能差异可能很大:

8.23 ns -- 分配元组
0.32 ns -- 分配 KeyValuePair (快 25 倍!)

1.93 ns -- 将元组作为参数传递
2.57 ns -- 将 KeyValuePair 作为参数传递

1.91 ns -- 返回元组
6.09 ns -- 返回 KeyValuePair

2.79 ns -- 从列表中加载元组
4.18 ns -- 从列表中加载 KeyValuePair

【讨论】:

    【解决方案4】:

    你真的问错了问题,正确的问题是使用 Class(Tuple)_ 比 Struct(KVP) 更好,在这种情况下,答案就是你想用它们做什么,答案在这里给出@987654321 @

    【讨论】:

    • 他问对了问题。对于明确暗示的用途,哪个更好的问题。
    • @Greg 问题是巧克力和苏打水哪个更好,但是具体问题没有意义,最好作为食品和饮料的一般问题来解决
    • 事实上的问题是“我什么时候应该使用元组与密钥对?”。这是一个合理的问题。我认为你只是停留在“更好”这个词的语义上。
    猜你喜欢
    • 2011-02-21
    • 2013-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-07
    • 1970-01-01
    • 2019-06-06
    相关资源
    最近更新 更多