C# 用c对数组进行散列#
简短问题 如何为C# 用c对数组进行散列#,c#,.net,arrays,hash,C#,.net,Arrays,Hash,简短问题 如何为数组实现GetHashCode 详细信息 我有一个覆盖等于的对象,检查: this.array[n] == otherObject.array[n] 对于数组中的所有n 当然,我应该实现互补的GetHashCode。 我想知道是否有.NET的方法可以做到这一点,或者我是否应该实现自己的方法,比如 hash = hash ^ array[n] 澄清 我的对象包含一个数组,我对数组元素的GetHashCode感兴趣。我的数组等价代码只是一个例子——正如我的问题所说,但可能我不清楚
数组实现GetHashCode
详细信息
我有一个覆盖等于的对象,检查:
this.array[n] == otherObject.array[n]
对于数组中的所有n
当然,我应该实现互补的GetHashCode
。
我想知道是否有.NET的方法可以做到这一点,或者我是否应该实现自己的方法,比如
hash = hash ^ array[n]
澄清
我的对象包含一个数组,我对数组元素的GetHashCode感兴趣。我的数组等价代码只是一个例子——正如我的问题所说,但可能我不清楚,我感兴趣的是GetHashCode
(而不是Equals
)。我说我自然应该实现互补的GetHashCode
,因为一旦Equals
被覆盖(为了Dictionary
等能够正确运行),就需要.NET实现它。谢谢。我不同意您自然地在数组上实现GetHashCode
您必须根据每次更改对其进行更新
或者动态计算
我会在飞行中直接比较
SequenceEquals将使用默认的相等比较器,因此您还应该实现
public bool Equals
0在数组中的对象上
他有一个例子
public static void SequenceEqualEx1()
{
Pet pet1 = new Pet { Name = "Turbo", Age = 2 };
Pet pet2 = new Pet { Name = "Peanut", Age = 8 };
// Create two lists of pets.
List<Pet> pets1 = new List<Pet> { pet1, pet2 };
List<Pet> pets2 = new List<Pet> { pet1, pet2 };
bool equal = pets1.SequenceEqual(pets2);
Console.WriteLine(
"The lists {0} equal.",
equal ? "are" : "are not");
}
publicstaticvoidsequenceequalex1()
{
宠物1=新宠物{Name=“Turbo”,年龄=2};
宠物pet2=新宠物{Name=“peant”,年龄=8};
//创建两个宠物列表。
列表pets1=新列表{pet1,pet2};
List pets2=新列表{pet1,pet2};
bool equal=pets1.SequenceEqual(pets2);
控制台写入线(
“列表{0}相等。”,
平等?“是”:“不是”);
}
要使用数组元素计算哈希代码,可以将数组强制转换为,然后调用该方法,并传递数组中元素类型的比较器
(强制转换是必需的,因为数组类显式实现了该方法。)
例如,如果您的对象有一个int
数组,则可以实现如下GetHashCode:
public override int GetHashCode()
{
return ((IStructuralEquatable)this.array).GetHashCode(EqualityComparer<int>.Default);
}
public override int GetHashCode()
{
返回((IsStructuralEquatable)this.array).GetHashCode(EqualityComparer.Default);
}
如果您感到好奇,下面是Array类如何实现GetHashCode方法(从中):
内部静态int组合hashcode(int h1,int h2){
返回((h1=8?this.Length-8:0);i
如您所见,当前的实现只使用数组的最后八个元素。这取决于您想要什么
Michael在上面回答的一个选项是基于数组元素使用哈希代码。这将符合等值语义。但是,因为“作为指导原则,对象的哈希在对象的整个生命周期内必须相同”你必须确保你的数组在得到它的hashcode后不会改变。拥有一个要求它永远不会改变的非不变容器听起来很容易出错
您的另一个(IMO更好的选择)是切换到不可变容器(即不可变数组),然后使用基于值的哈希代码。您可以如上所述使用IsStructuralEquatable
,也可以更一般地使用:
public override GetHashCode() =>
Value.Aggregate(0, (total, next) => HashCode.Combine(total, next));
也适用于其他不可变的集合。
< P>使用当前框架可以考虑使用
int value=0;
for (var i = 0;i< this.array.Length; i++)
{
value=HashCode.Combine(this.array[i],value);
}
int值=0;
for(var i=0;i
看看贴出的答案。换句话说,你最好实现自己的变体或使用其他工具,你不能对数组使用GetHashCode()
或Equals()
为什么不使用this.array[n].Equals(otherObject.array[n])
对于n
?如果要比较两个数组是否相等,可以使用SequenceEqual
extension@cz:请澄清array
是否是覆盖Equals和GetHashCode的对象中的字段。OP的可能副本在包含数组的对象上实现了Equals。这是自然的l在该对象上也实现GetHashCode。@MichaelLiu不是我读取它的方式。我没有读取包含数组的对象。我将其作为数组覆盖中的对象读取。数组[n]==其他对象。数组[n]。为什么数组中的一个对象会有一个引用此数组的Equals方法?这意味着你有一个对象数组,而对象数组又包含数组。不,这并不意味着。你正在读一些不存在的东西。我同意数组中的一个项为什么需要引用数组?有一个巧妙的内置方法来比较two数组使用数组中项的默认相等比较器。“我不同意您应该在数组上自然实现GetHashCode”-如果在重写相等时不实现GetHashCode,则字典的行为非常奇怪,因此我确实需要GetHashCode。使用array.GetHashCode()这肯定是错误的,因为它将为两个元素相等的数组返回不同的值,而OP需要它返回相同的值。显然,您必须确保数组的内容在获得其结构哈希代码后不会被修改,如果数组是对象的私有成员,这是可能的。(假设数组的大小是固定的,我想这就是你所说的“添加/删除元素”的意思。)你说得对!编辑了我的答案。似乎没有“好”的解决方案可以将具有值语义的非不变集合存储为其他集合的元素
int value=0;
for (var i = 0;i< this.array.Length; i++)
{
value=HashCode.Combine(this.array[i],value);
}