Svi*_*ish 54 c# arrays generics hashcode
我有一个包含以下两个属性的类:
public int Id { get; private set; }
public T[] Values { get; private set; }
Run Code Online (Sandbox Code Playgroud)
我做了它IEquatable<T>并覆盖了object.Equals这样的:
public override bool Equals(object obj)
{
return Equals(obj as SimpleTableRow<T>);
}
public bool Equals(SimpleTableRow<T> other)
{
// Check for null
if(ReferenceEquals(other, null))
return false;
// Check for same reference
if(ReferenceEquals(this, other))
return true;
// Check for same Id and same Values
return Id == other.Id && Values.SequenceEqual(other.Values);
}
Run Code Online (Sandbox Code Playgroud)
当object.Equals我有覆盖时,我GetHashCode当然也必须覆盖.但是我应该实现什么代码?如何从通用数组中创建哈希码?我如何将它与Id整数相结合?
public override int GetHashCode()
{
return // What?
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*ell 83
由于这个帖子中出现的问题,我发布了另一个回复,显示如果你弄错了会发生什么......主要是你不能使用数组GetHashCode(); 正确的行为是,当你运行它时没有打印警告...切换注释以修复它:
using System;
using System.Collections.Generic;
using System.Linq;
static class Program
{
static void Main()
{
// first and second are logically equivalent
SimpleTableRow<int> first = new SimpleTableRow<int>(1, 2, 3, 4, 5, 6),
second = new SimpleTableRow<int>(1, 2, 3, 4, 5, 6);
if (first.Equals(second) && first.GetHashCode() != second.GetHashCode())
{ // proven Equals, but GetHashCode() disagrees
Console.WriteLine("We have a problem");
}
HashSet<SimpleTableRow<int>> set = new HashSet<SimpleTableRow<int>>();
set.Add(first);
set.Add(second);
// which confuses anything that uses hash algorithms
if (set.Count != 1) Console.WriteLine("Yup, very bad indeed");
}
}
class SimpleTableRow<T> : IEquatable<SimpleTableRow<T>>
{
public SimpleTableRow(int id, params T[] values) {
this.Id = id;
this.Values = values;
}
public int Id { get; private set; }
public T[] Values { get; private set; }
public override int GetHashCode() // wrong
{
return Id.GetHashCode() ^ Values.GetHashCode();
}
/*
public override int GetHashCode() // right
{
int hash = Id;
if (Values != null)
{
hash = (hash * 17) + Values.Length;
foreach (T t in Values)
{
hash *= 17;
if (t != null) hash = hash + t.GetHashCode();
}
}
return hash;
}
*/
public override bool Equals(object obj)
{
return Equals(obj as SimpleTableRow<T>);
}
public bool Equals(SimpleTableRow<T> other)
{
// Check for null
if (ReferenceEquals(other, null))
return false;
// Check for same reference
if (ReferenceEquals(this, other))
return true;
// Check for same Id and same Values
return Id == other.Id && Values.SequenceEqual(other.Values);
}
}
Run Code Online (Sandbox Code Playgroud)
Dus*_*ell 31
FWIW,在哈希码中使用Values的内容非常危险.如果您能保证永远不会改变,那么您应该这样做.但是,由于它暴露,我不认为保证它是可能的.对象的哈希码永远不会改变.否则,它将作为Hashtable或Dictionary中的键丢失其值.考虑使用对象作为Hashtable中的键的难以发现的错误,其哈希码因外部影响而发生变化,您无法再在Hashtable中找到它!
| 归档时间: |
|
| 查看次数: |
44530 次 |
| 最近记录: |