Giới thiệu
Phương thức ảo GetHashCode() của Object trả về mã băm (hash code) 32-bit signed integer cho đối tượng. Mặc định implementation dựa trên tham chiếu (reference equality) cho reference type, hoặc giá trị cho value type. Dùng cho hash-based collections: Dictionary, HashSet, Hashtable.
Cú pháp
public virtual int GetHashCode();
Ví dụ 1 - Object và String mặc định
using System;
public class Demo
{
public static void Main()
{
Object ob = new Object();
String str = "Jim";
Type type1 = ob.GetType();
Type type2 = str.GetType();
Console.WriteLine("Hash Code của Type Object = " + type1.GetHashCode());
Console.WriteLine("Hash Code của Type String = " + type2.GetHashCode());
}
}
Kết quả
Hash Code của Type Object = 30015890 Hash Code của Type String = 21083178
Ví dụ 2 - Override GetHashCode cho struct
using System;
public struct Value
{
private int v1;
private int v2;
private int v3;
public Value(int v1, int v2, int v3)
{
this.v1 = v1;
this.v2 = v2;
this.v3 = v3;
}
public override int GetHashCode()
{
// Kết hợp hash code của các trường (cách phổ biến)
return Tuple.Create(v1, v2, v3).GetHashCode();
// Hoặc: return HashCode.Combine(v1, v2, v3); // .NET Core 2.1+
}
}
public class Demo
{
public static void Main()
{
Value v = new Value(1, 7, 12);
Console.WriteLine(v.GetHashCode()); // 1258
v = new Value(12, 8, 7);
Console.WriteLine(v.GetHashCode()); // 12803
v = new Value(8, 7, 12);
Console.WriteLine(v.GetHashCode()); // 8931
}
}
Kết quả
1258 12803 8931
Quy tắc quan trọng khi override GetHashCode()
- Consistency: Nếu
Equals(a, b) == truethìa.GetHashCode() == b.GetHashCode()bắt buộc true. - Stability: Hash code không đổi trong vòng đời object (trường hợp dùng trong hash table). Nên chỉ dùng các trường immutable (readonly).
- Distribution: Phân bố đều để giảm collision.
- Performance: Tính toán nhanh.
Cách combine hash code hiện đại (.NET Core 2.1+)
public override int GetHashCode()
{
return HashCode.Combine(field1, field2, field3);
}
Lưu ý quan trọng
- Không dùng
GetHashCode()làm unique ID (có collision). - Không persist hash code (lưu DB, file) vì có thể khác giữa phiên bản/runtime/architecture.
- Struct mặc định có GetHashCode() dựa trên trường đầu tiên non-null (có thể gây collision cao).
- Record types (C# 9+) tự động generate Equals/GetHashCode dựa trên properties.