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);
}