【问题标题】:Are ValueTuples suitable as dictionary keys?ValueTuples 是否适合作为字典键?
【发布时间】:2018-12-18 10:31:38
【问题描述】:

我想这可能是一本方便的字典:

var myDict = new Dictionary<(int, int), bool>();

哈希会是什么样子?
等效的键类型(结构)是什么样的?

【问题讨论】:

  • 更简单的方法是使用字符串连接。 int[] 输入 = { 1, 2, 3 };字符串键 = string.Join("^",input.Select(x => x.ToString()));
  • @jdweng 如果您关心分配,那将是一个糟糕的主意
  • @MarcGravell:你什么意思?
  • @jdweng 我的意思是:您现在每次想要存储或检索一个值时都分配一个字符串 - 这在许多系统中是一个 巨大 问题。与使用 value-tuple 作为 key 相比,它在分配方面基本上是免费的。
  • @jdweng:没有理由这样做:您分配了大量不必要的数据(字符串连接),您花时间使用当前文化创建单个对象的字符串表示,然后您花更多的时间评估它们的相等性(valuetype.equals 是微不足道的),最后使用分隔符连接字符串表示通常是一个坏主意,因为您需要确保不会意外创建键冲突。 ValueTuple 是一个结构体,另一方面,没有分配,没有 GC,简单的相等性检查。

标签: c# dictionary valuetuple


【解决方案1】:

是的,没关系。 ValueTuple&lt;...&gt; 系列是一组定义明确的常规结构,具有正确的相等性和哈希码行为,可用作字典键。有一个轻微警告,它们是可变的而不是不可变的,但是由于复制语义,这在这种情况下并没有真正影响它们(这意味着:你不能在密钥之后更改它已添加,因为您只是更改了密钥的不同副本;这与可变类作为密钥的问题非常不同)。你可以看到code here

【讨论】:

  • 如果我不是很清楚:(int,int) 使用链接文件中的public struct ValueTuple&lt;T1, T2&gt;,特别是ValueTuple&lt;int,int&gt;
  • 首先他们将Tuple 设置为不可变的类,然后将ValueTuple 设置为结构,但使其可变。
  • @Groo 确实如此,我认为这是一种有效且务实的做法;一个可变类Tuple&lt;...&gt;family 会非常危险;一个可变结构ValueTuple&lt;...&gt;family 更安全,并且可以启用一些场景而不会导致任何关键的平等问题。我可能更喜欢它是不可变的(我爱我一些readonly struct),但是......嗯,在这种情况下它是有道理的。
  • Tuple 是可变的我没有问题,但对我来说,它首先是一个类是没有意义的。我真的很喜欢 .NET 减少分配的方式(例如 Span&lt;T&gt;),我希望 both 正如你所写的那样不可变。
【解决方案2】:

作为值类型,ValueTuple 的哈希遵循默认实现,它基于成员的值:

如果值类型不覆盖 GetHashCode,则 ValueType.GetHashCode 基类的方法使用反射来计算哈希码 基于类型字段的值。换句话说,值类型 具有相同值的字段具有相同的哈希码。

元组是可变的,但由于它们是按值复制,因此您可以安全地将它们用作字典键。如果您使用元组类型的变量,则可能会出现问题,在Dictionary.Add 中使用此变量,然后修改此变量并尝试使用与键相同的变量来访问字典中的关联值。在这种情况下,您将无法在字典中找到它。

等效结构如下:

MyStruct : struct
{
    public int A;
    public int B;
}

【讨论】:

  • "等效结构" - 将实现 IEquatable&lt;MyStruct&gt; 并具有自定义 GetHashCode()/Equals(object)/Equals(MyStruct) 实现 - 是的,没有它们它会工作,但它会导致所有“受约束的调用”检查和EqualityComparer&lt;T&gt;.Default 实现中的装箱 - 这会大大改变行为
  • 是的,如果有人知道的话,我对GetHashCode()IEquatable&lt;&gt; 等感兴趣。
  • @MarcGravell,您能详细说明一下吗?除了导致额外的分配和拆箱操作之外,恐怕我无法理解装箱将如何进入。
  • @Nick 它不会“妨碍”改变最终结果,但它会对它如何到达那里产生重大影响,因此:尽管表现功能上等同,但它的性能特征将非常不同。我是那些认为“非常不同的性能特征”是行为的重要组成部分的人之一
  • @MarcGravell,很公平。谢谢!
猜你喜欢
  • 2016-05-04
  • 2011-10-25
  • 2011-10-25
  • 2014-04-14
  • 1970-01-01
  • 1970-01-01
  • 2011-07-21
  • 2015-04-18
  • 2012-07-31
相关资源
最近更新 更多