Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

เมธอด Object.GetHashCode() ใน C# พร้อมตัวอย่าง

เมธอด Object.GetHashCode() ใน C# ใช้คืนค่า hash code (รหัสแฮช) ของอ็อบเจ็กต์ — ใช้เป็นค่าเริ่มต้นสำหรับ hash-based collections เช่น Dictionary, HashSet, Hashtable

ไวยากรณ์ (Syntax)

public virtual int GetHashCode();

ตัวอย่างที่ 1: GetHashCode ของ Object และ String

using System;

public class Demo
{
    public static void Main()
    {
        object obj = new object();
        string str = "Jim";

        Type type1 = obj.GetType();
        Type type2 = str.GetType();

        Console.WriteLine("Hash Code = " + type1.GetHashCode());
        Console.WriteLine("Hash Code = " + type2.GetHashCode());
    }
}

ผลลัพธ์

Hash Code = 30015890
Hash Code = 21083178

ตัวอย่างที่ 2: Override GetHashCode ใน Struct (Value Type)

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()
    {
        return Tuple.Create(v1, v2, v3).GetHashCode();
    }
}

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

ผลลัพธ์

1258
12803
8931

สรุปและแนวทางปฏิบัติ (Best Practices)

  • Hash code ใช้สำหรับ hash-based collections — Dictionary, HashSet, Hashtable ใช้เพื่อจัดเก็บ/ค้นหา O(1)
  • กฎสำคัญ: หาก a.Equals(b) == true แล้ว a.GetHashCode() == b.GetHashCode() ต้องเป็น true ด้วย (แต่กลับกันไม่จำเป็น)
  • Override ได้เฉพาะเมื่อ Override Equals() ด้วย — ต้อง override คู่กันเสมอ
  • สำหรับ reference types — default implementation ใช้ object identity (reference)
  • สำหรับ value types (struct) — default ใช้ reflection/field values — ช้า ควร override เอง
  • Hash code ไม่ต้อง unique — ชน (collision) ได้ แต่อย่างน้อยควรกระจายดี
  • Hash code ไม่ควรเปลี่ยนแปลง** ระหว่างชีวิตของอ็อบเจ็กต์ (ถ้าใช้เป็น key ใน Dictionary)

รูปแบบการ Override GetHashCode ที่ดี

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }

    public override bool Equals(object obj)
    {
        return obj is Person other &&
               FirstName == other.FirstName &&
               LastName == other.LastName &&
               Age == other.Age;
    }

    public override int GetHashCode()
    {
        // Pattern มาตรฐาน: prime * hash + fieldHash
        unchecked // ป้องกัน overflow checking
        {
            int hash = 17;
            hash = hash * 23 + (FirstName?.GetHashCode() ?? 0);
            hash = hash * 23 + (LastName?.GetHashCode() ?? 0);
            hash = hash * 23 + Age.GetHashCode();
            return hash;
        }
    }
}

// หรือใช้ Tuple (สะดวก แต่ช้ากว่าเล็กน้อย)
public override int GetHashCode() => Tuple.Create(FirstName, LastName, Age).GetHashCode();

// .NET Core 2.1+ / NET 5+ - ใช้ HashCode.Combine (เร็วและสะดวก)
public override int GetHashCode() => HashCode.Combine(FirstName, LastName, Age);

ข้อควรระวัง

  • อย่าใช้ GetHashCode() สำหรับ: persistent storage, distributed systems, security/cryptography — ไม่รับประกันความสม่ำเสมอระหว่าง process/run/version
  • String.GetHashCode() อาจต่างกันระหว่าง 32-bit/64-bit process และ .NET versions
  • สำหรับ cryptographic hash ใช้ System.Security.Cryptography (SHA256, MD5, etc.)