0Pricing
C# Academy · Pelajaran

Kesetaraan & hashing (nilai vs referensi)

Pahami kesetaraan referensi dan nilai, timpa Equals/GetHashCode dengan benar, implementasikan IEquatable , dan gunakan pembanding khusus pada himpunan/kamus.

Kesetaraan & hashing (nilai vs referensi) adalah pelajaran C# Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 3. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar C# Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus C# Academy mencakup 3 pelajaran total.

Dasar-dasar kesetaraan

Tujuan: Membuat kesetaraan bekerja sesuai harapan Anda.

  • Kesetaraan referensi vs nilai
  • Kontrak Equals + GetHashCode
  • IEquatable<T> untuk kecepatan
  • Pembanding khusus saat Anda tidak dapat mengubah tipe

Jebakan kesetaraan referensi

Kelas secara bawaan menggunakan kesetaraan referensi. Dua objek terpisah dengan data yang sama tidak setara kecuali Anda mengimplementasikan kesetaraan nilai.

using System;
using System.Collections.Generic;

public sealed class Point // no overrides
{
  public int X;
  public int Y;
  public Point(int x, int y){ X = x; Y = y; }
}

public class Program
{
  public static void Main(string[] args)
  {
    Point a = new Point(1, 2);
    Point b = new Point(1, 2);

    Console.WriteLine("a == b ? " + (a == b)); // reference equality: False
    Console.WriteLine("a.Equals(b) ? " + a.Equals(b)); // False

    HashSet<Point> set = new HashSet<Point>();
    set.Add(a);
    Console.WriteLine("Contains b? " + set.Contains(b)); // False (unexpected)
  }
}

Kesetaraan nilai diimplementasikan

Implementasikan IEquatable<T>, timpa Equals dan GetHashCode. Nilai hash harus konsisten dengan kesetaraan: objek yang setara → hash yang sama.

using System;
using System.Collections.Generic;

public sealed class ValuePoint : IEquatable<ValuePoint>
{
  public int X;
  public int Y;
  public ValuePoint(int x, int y){ X = x; Y = y; }

  public bool Equals(ValuePoint other)
  {
    if (ReferenceEquals(other, null)) return false;
    if (ReferenceEquals(this, other)) return true;
    return X == other.X && Y == other.Y;
  }

  public override bool Equals(object obj)
  {
    return Equals(obj as ValuePoint);
  }

  public override int GetHashCode()
  {
    // Simple, stable combination (avoid randomness)
    unchecked
    {
      int hash = 17;
      hash = hash * 31 + X.GetHashCode();
      hash = hash * 31 + Y.GetHashCode();
      return hash;
    }
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    ValuePoint a = new ValuePoint(1, 2);
    ValuePoint b = new ValuePoint(1, 2);

    Console.WriteLine("a.Equals(b)? " + a.Equals(b)); // True

    HashSet<ValuePoint> set = new HashSet<ValuePoint>();
    set.Add(a);
    Console.WriteLine("Contains b? " + set.Contains(b)); // True (value semantics)
  }
}

Pembanding khusus

Berikan pembanding khusus IEqualityComparer<T> kepada HashSet/Dictionary jika Anda tidak dapat mengubah tipe itu sendiri.

using System;
using System.Collections.Generic;

public sealed class Person // imagine from a library; cannot edit
{
  public string Name;
  public int BirthYear;
  public Person(string name, int year){ Name = name; BirthYear = year; }
}

public sealed class PersonComparer : IEqualityComparer<Person>
{
  public bool Equals(Person a, Person b)
  {
    if (ReferenceEquals(a, b)) return true;
    if (ReferenceEquals(a, null) || ReferenceEquals(b, null)) return false;
    return a.Name == b.Name && a.BirthYear == b.BirthYear;
  }

  public int GetHashCode(Person p)
  {
    if (ReferenceEquals(p, null)) return 0;
    unchecked
    {
      int h = 23;
      h = h * 31 + (p.Name == null ? 0 : p.Name.GetHashCode());
      h = h * 31 + p.BirthYear.GetHashCode();
      return h;
    }
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    Person p1 = new Person("Ada", 1815);
    Person p2 = new Person("Ada", 1815);

    HashSet<Person> set = new HashSet<Person>(new PersonComparer());
    set.Add(p1);
    Console.WriteLine("Contains p2? " + set.Contains(p2)); // True via comparer
  }
}

Kontrak & jebakan

Aturan:

  • Jika Equals(a,b) bernilai true ⇒ GetHashCode(a) == GetHashCode(b)
  • Kesetaraan harus bersifat refleksif, simetris, transitif
  • Jika memungkinkan, gunakan field yang tidak dapat berubah untuk hashing
  • Jangan gunakan nilai acak dalam GetHashCode

Catatan struct vs class

Struct secara bawaan membandingkan berdasarkan field (semantik nilai). Class membandingkan berdasarkan referensi kecuali Anda mengimplementasikan kesetaraan nilai.

using System;

public struct PointS // struct: value type
{
  public int X;
  public int Y;
  public PointS(int x, int y){ X = x; Y = y; }
}

public class Program
{
  public static void Main(string[] args)
  {
    PointS a = new PointS(1, 2);
    PointS b = new PointS(1, 2);
    Console.WriteLine("Struct equality: " + a.Equals(b)); // True by default (field-wise)
  }
}

Kontrak kesetaraan untuk koleksi

Pemeriksaan singkat: Untuk memberikan kesetaraan nilai pada class yang berfungsi dalam HashSet dan Dictionary, apa yang harus Anda implementasikan?

Ringkasan

Ringkasan: Class memerlukan Equals/GetHashCode (dan sering kali IEquatable<T>) untuk semantik nilai; gunakan pembanding khusus jika tipe tidak dapat diedit.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Kesetaraan & hashing (nilai vs referensi)” gratis?

Ya — teks lengkap “Kesetaraan & hashing (nilai vs referensi)” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus C# Academy, upgrade ke CoddyKit PRO. Kursus C# Academy mencakup 3 pelajaran total.

Apa yang akan aku pelajari di “Kesetaraan & hashing (nilai vs referensi)”?

Pahami kesetaraan referensi dan nilai, timpa Equals/GetHashCode dengan benar, implementasikan IEquatable , dan gunakan pembanding khusus pada himpunan/kamus. Kamu berlatih C# Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai C# Academy?

Tidak diperlukan pengalaman sebelumnya. C# Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 3.

Berapa lama pelajaran “Kesetaraan & hashing (nilai vs referensi)” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran C# Academy ini?

Ya. Setiap pelajaran C# Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. HashSet , SortedSet , Queue , Stack
  2. ConcurrentDictionary , koleksi immutable
  3. Kesetaraan & hashing (nilai vs referensi)
← Kembali ke C# Academy