繁体   English   中英

C#Struct字典键不适用于数组成员

[英]C# Struct dictionary key not working with array member

我正在尝试创建一个在构造过程中采用可变数量参数的结构,目的是将此对象用作字典键(我的.Net版本不支持Tuple类型):

struct TupleKey
{
    int[] args;
    public TupleKey(params int[] args) { this.args = args; }
}

但是,当我将此struct用作字典的键时, ContainsKey方法将返回false。

var d = new Dictionary<TupleKey, int>();
d.Add(new TupleKey(1, 1), 1);
Console.WriteLine(d.ContainsKey(new TupleKey(1,1)));  // false!?

这是怎么回事? 在结构中使用可变对象(如数组)是否存在问题?

自定义struct的默认相等和哈希代码实现将基于其成员的默认相等和哈希代码方法(在您的情况下为数组)。 该数组使用基于引用的身份,而不是基于值的身份。 如果要使具有相同值的不同数组相等,则需要重写EqualsGetHashCode以依赖于数组的值。

通常,.NET中的类型会尝试定义Equals ,以便如果xy是类的私有字段,则除非该类写入这些字段,否则x.Equals(y)值无法更改。 如果xy是可变引用类型,则意味着x.Equals(y)可以为true的唯一方法是xy标识同一对象。 如果xy标识状态恰好相同的不同对象时x.Equals(y)返回true,并且在其他地方引用这些对象之一的代码将修改其状态,则外部代码可以更改该值不能访问xyx.Equals(y)

我认为可以合理地认为.NET缺乏“不变数组”类型。 如果存在这样的类型,那么它们是不可变的,可以保证如果两个实例包含相同的项目,它们将永远这样做。 但是,由于.NET没有任何此类类型,因此必须忍受这种限制。

最好的办法可能是让您的结构的构造函数构造一个数组,该数组比传入的数组长一个元素,并包含原始数组内容的副本以及其中值的哈希值。 这样,该数组将永远不会暴露给外部代码,因此可以保证永远不会被修改。 您的equals方法可以检查与您的类型进行比较的对象是否是相同类型的另一个结构,如果是,则检查数组的长度是否相同,存储的哈希值是否匹配,以及是否是否所有其他项匹配。 然后,您的GetHashCode值应返回存储在额外数组插槽中的哈希值。 如果这样做,还应该实现IEquatable<yourOwnType>

请注意,虽然可以使用字段而不是数组插槽来保存哈希值,但是使用数组插槽会更有效,并且可以避免不正确的多线程代码创建其哈希值的结构实例的可能性。与数组的内容不同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM