我的理解是你通常应该使用xor和GetHashCode()生成一个int来通过它的值来识别你的数据(而不是通过它的引用).这是一个简单的例子:
class Foo
{
int m_a;
int m_b;
public int A
{
get { return m_a; }
set { m_a = value; }
}
public int B
{
get { return m_b; }
set { m_b = value; }
}
public Foo(int a, int b)
{
m_a = a;
m_b = b;
}
public override int GetHashCode()
{
return A ^ B;
}
public override bool Equals(object obj)
{
return this.GetHashCode() == obj.GetHashCode();
}
}
Run Code Online (Sandbox Code Playgroud)
我的想法是,我想根据属性A和B的值将Foo的一个实例与另一个实例进行比较.如果Foo1.A == Foo2.A和Foo1.B == Foo2.B,那么我们就有了相等性. …
可以调用GetHashCode作为从Equals覆盖内部测试相等性的方法吗?
例如,这段代码可以接受吗?
public class Class1
{
public string A
{
get;
set;
}
public string B
{
get;
set;
}
public override bool Equals(object obj)
{
Class1 other = obj as Class1;
return other != null && other.GetHashCode() == this.GetHashCode();
}
public override int GetHashCode()
{
int result = 0;
result = (result ^ 397) ^ (A == null ? 0 : A.GetHashCode());
result = (result ^ 397) ^ (B == null ? 0 : B.GetHashCode());
return result;
}
}
Run Code Online (Sandbox Code Playgroud) Google Guava提供了很好的帮助来实现equals,hashCode如下例所示:
public int hashCode() {
return Objects.hashCode(lastName, firstName, gender);
}
Run Code Online (Sandbox Code Playgroud)
是否有类似的Microsoft .NET库?
为什么
17m.GetHashCode() == 17d.GetHashCode()
(m =十进制,d =双)
此外,正如预期的那样
17f.GetHashCode() != 17d.GetHashCode()
(f =浮点数)
对于net3.5和net4.0来说,这似乎都是正确的.
据我了解,这些类型的内部位表示是完全不同的.那么为什么十进制和双精度类型的哈希码对于相等的初始化值相等呢?在计算哈希值之前是否发生了一些转换?
我发现源代码Double.GetHashCode()是这样的:
//The hashcode for a double is the absolute value of the integer representation
//of that double.
//
[System.Security.SecuritySafeCritical] // auto-generated
public unsafe override int GetHashCode() {
double d = m_value;
if (d == 0) {
// Ensure that 0 and -0 have the same hash code
return 0;
}
long value = *(long*)(&d);
return unchecked((int)value) ^ ((int)(value >> …Run Code Online (Sandbox Code Playgroud) 我有覆盖GetHashCode,Equals并且两种方法为不同的对象提供相同的结果,但为什么仍然得到假?
class Program
{
static void Main(string[] args)
{
Console.WriteLine(new Person("james") == new Person("james"));
Console.ReadKey();
}
}
class Person
{
private string Name;
public Person(string name)
{
Name = name;
}
public override int GetHashCode()
{
return 1;
}
public override bool Equals(object obj)
{
return true;
}
}
Run Code Online (Sandbox Code Playgroud) GetHashCode如果我的对象被认为是相等的,如果它们中至少有一个字段匹配,那么覆盖该情况的函数的最佳方法是什么.
在泛型Equals方法的情况下,示例可能如下所示:
public bool Equals(Whatever other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
// Considering that the values can't be 'null' here.
return other.Id.Equals(Id) || Equals(other.Money, Money) ||
Equals(other.Code, Code);
}
Run Code Online (Sandbox Code Playgroud)
尽管如此,我GetHashCode对这个案例的良好实施感到困惑.
该怎么做?
谢谢.
该计划正在实施此实施:
class Instrument
{
public string ClassCode { get; set; }
public string Ticker { get; set; }
public override string ToString()
{
return " ClassCode: " + ClassCode + " Ticker: " + Ticker + '.';
}
}
Run Code Online (Sandbox Code Playgroud)
但是因为我需要在Dictionary中使用Instrument,所以我决定实现equals/hashcode:
class Instrument
{
public string ClassCode { get; set; }
public string Ticker { get; set; }
public override string ToString()
{
return " ClassCode: " + ClassCode + " Ticker: " + Ticker + '.';
}
public override bool …Run Code Online (Sandbox Code Playgroud) 我已经实现了一个重载==和!=运算符的类.
这似乎工作正常; 但是,我得到了警告'type' defines operator == or operator != but does not override Object.Equals(object o).
好的,所以我实施了Equals.但现在我收到了警告'type' defines operator == or operator != but does not override Object.GetHashCode().
这会在某个时候结束吗?或者我是否因为我想超载==而徘徊于永无止境的需求之路!=?
我想为字符串生成一个整数哈希码,它将永远保持不变; 即相同的字符串应始终产生相同的哈希码.
散列不必是加密安全的,它不会用于密码或敏感数据.
我的第一次尝试是使用.net框架string.GetHashCode()函数.但是在阅读消息来源后,我发现了以下内容:
Run Code Online (Sandbox Code Playgroud)// We want to ensure we can change our hash function daily. // This is perfectly fine as long as you don't persist the // value from GetHashCode to disk or count on String A // hashing before string B. Those are bugs in your code. hash1 ^= ThisAssembly.DailyBuildNumber;
这似乎表明哈希码不会保持不变.
如果是这样,框架是否有另一种方法来生成可重复的哈希码?或者GetHashCode的代码是否是实现我自己的代码的合理起点?
我正在寻找尽可能轻巧和快速的东西.
我找到了System.Security.Cryptography.MD5,但对于一个简单的int32哈希码来说这似乎有点过头了,我担心开销.至少它需要从字符串转换为字节数组,从字节数组转换为int,并MD5()为每个散列创建新对象,或管理某些静态共享MD5对象().
我正在实施IEquatable<T>,但我很难就可变GetHashCode类的覆盖达成共识。
以下资源都提供了一个实现,GetHashCode如果对象发生更改,则在对象的生命周期内将返回不同的值:
但是,此链接指出GetHashCode不应为可变类型实现,因为如果对象是集合的一部分,则可能会导致不良行为(这也一直是我的理解)。
有趣的是,MSDN 示例实现了GetHashCode仅使用不可变属性,这符合我的理解。但我很困惑为什么其他资源不涵盖这一点。他们真的错了吗?
如果一个类型根本没有不可变属性,编译器会GetHashCode在我重写时警告该类型丢失Equals(object)。在这种情况下,我应该实现它并只调用base.GetHashCode()或禁用编译器警告,还是我错过了某些内容并且GetHashCode应该始终被覆盖和实现?事实上,如果建议不GetHashCode应该为可变类型实现,为什么还要为不可变类型实现呢?与默认实现相比,它只是为了减少冲突GetHashCode,还是实际上添加了更多有形的功能?
总结我的问题,我的困境是,GetHashCode在可变对象上使用意味着如果对象的属性发生变化,它可以在对象的生命周期内返回不同的值。但不使用它意味着比较可能等效的对象的好处会丢失,因为它将始终返回唯一值,因此集合将始终回退到使用Equals其操作。
输入此问题后,“类似问题”框中弹出了另一个问题,似乎涉及同一主题。答案似乎非常明确,因为在GetHashCode实现中只应使用不可变属性。如果没有,那就干脆不写。Dictionary<TKey, TValue>尽管不是 O(1) 性能,但仍然可以正常运行。
gethashcode ×10
c# ×9
.net ×5
equals ×3
decimal ×1
double ×1
guava ×1
hash ×1
hashcode ×1
iequatable ×1
immutability ×1
java ×1
matching ×1
mutable ×1
properties ×1
string ×1