0Pricing
C# Academy · บทเรียน

การนำ IEquatable ไปใช้

จัดเตรียมการตรวจสอบความเท่ากันที่ปลอดภัยต่อชนิดข้อมูลด้วย Equals

การนำ IEquatable ไปใช้ เป็นบทเรียน C# Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C# Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน

เหตุใดจึงใช้ IEquatable<T>?

IEquatable<T> จัดเตรียมเมธอด Equals(T other) ที่มีชนิดข้อมูลชัดเจน ช่วยหลีกเลี่ยงการบรรจุค่าสำหรับชนิดข้อมูลค่าและหลีกเลี่ยงการแปลงชนิดสำหรับชนิดข้อมูลอ้างอิง ทำให้การตรวจสอบความเท่ากันทั้งเร็วขึ้นและชัดเจนขึ้น

การนำอินเทอร์เฟซไปใช้

นำ IEquatable<T> ไปใช้และจัดเตรียม Equals(T other) นอกจากนี้ควรโอเวอร์ไรด์ object.Equals และ GetHashCode ที่สืบทอดมา เพื่อให้เส้นทางทั้งหมดสอดคล้องกัน

using System;

public struct Point : IEquatable<Point>
{
    public int X, Y;
    public Point(int x, int y) { X = x; Y = y; }

    public bool Equals(Point other) => X == other.X && Y == other.Y;
    public override bool Equals(object obj) => obj is Point p && Equals(p);
    public override int GetHashCode() => HashCode.Combine(X, Y);
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Point(1, 2).Equals(new Point(1, 2)));
    }
}

หลีกเลี่ยงการบรรจุค่าสำหรับโครงสร้าง

object.Equals(object) ที่ไม่ใช้ชนิดข้อมูลทั่วไปจะบรรจุอาร์กิวเมนต์ที่เป็นโครงสร้าง ส่วน Equals(Point other) ที่มีชนิดข้อมูลจาก IEquatable<T> จะรับโครงสร้างโดยตรง จึงไม่เกิดการจองหน่วยความจำ

using System;

public struct Point : IEquatable<Point>
{
    public int X, Y;
    public Point(int x, int y) { X = x; Y = y; }
    public bool Equals(Point other) => X == other.X && Y == other.Y; // no boxing
    public override bool Equals(object obj) => obj is Point p && Equals(p);
    public override int GetHashCode() => HashCode.Combine(X, Y);
}

public class Program
{
    public static void Main()
    {
        Point a = new Point(3, 4);
        Point b = new Point(3, 4);
        Console.WriteLine(a.Equals(b)); // calls the typed overload
    }
}

คอลเลกชันใช้ IEquatable<T>

List<T>.Contains, Dictionary และ HashSet จะเลือกใช้ IEquatable<T>.Equals หากมี การนำสิ่งนี้ไปใช้ทำให้การดำเนินการเหล่านี้มีประสิทธิภาพและถูกต้องสำหรับชนิดข้อมูลของคุณ

using System;
using System.Collections.Generic;

public struct Point : IEquatable<Point>
{
    public int X, Y;
    public Point(int x, int y) { X = x; Y = y; }
    public bool Equals(Point other) => X == other.X && Y == other.Y;
    public override bool Equals(object obj) => obj is Point p && Equals(p);
    public override int GetHashCode() => HashCode.Combine(X, Y);
}

public class Program
{
    public static void Main()
    {
        var list = new List<Point> { new Point(0, 0), new Point(1, 1) };
        Console.WriteLine(list.Contains(new Point(1, 1)));
    }
}

ชนิดข้อมูลอ้างอิงกับ IEquatable<T>

คลาสก็สามารถนำ IEquatable<T> ไปใช้ได้เช่นกัน เมธอด Equals ที่มีชนิดข้อมูลชัดเจนช่วยหลีกเลี่ยงการแปลงชนิด และคุณต้องจัดการกับ null อย่างชัดเจนสำหรับพารามิเตอร์อ้างอิง

using System;

public class Person : IEquatable<Person>
{
    public string Name;
    public Person(string name) { Name = name; }

    public bool Equals(Person other) => other != null && other.Name == Name;
    public override bool Equals(object obj) => Equals(obj as Person);
    public override int GetHashCode() => Name?.GetHashCode() ?? 0;
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Person("Ada").Equals(new Person("Ada")));
        Console.WriteLine(new Person("Ada").Equals((Person)null));
    }
}

ให้ object.Equals เรียกใช้เมธอดที่มีชนิดข้อมูลชัดเจน

รูปแบบที่สะอาดคือเขียนการเปรียบเทียบไว้เพียงครั้งเดียวใน Equals(T) แล้วให้ object.Equals ส่งต่อการทำงานไปยังเมธอดนั้น วิธีนี้รับประกันว่าทั้งสองเมธอดจะทำงานเหมือนกันทุกประการ

using System;

public struct Id : IEquatable<Id>
{
    public int Value;
    public Id(int value) { Value = value; }
    public bool Equals(Id other) => Value == other.Value;
    public override bool Equals(object obj) => obj is Id other && Equals(other);
    public override int GetHashCode() => Value;
}

public class Program
{
    public static void Main()
    {
        object boxed = new Id(5);
        Console.WriteLine(boxed.Equals(new Id(5)));
    }
}

การเปรียบเทียบหลายฟิลด์

สำหรับชนิดข้อมูลที่มีหลายฟิลด์ ให้เปรียบเทียบฟิลด์ทั้งหมดใน Equals อินสแตนซ์สองรายการจะเท่ากันก็ต่อเมื่อฟิลด์ที่เกี่ยวข้องทุกฟิลด์มีค่าตรงกัน

using System;

public struct DateRange : IEquatable<DateRange>
{
    public int Start, End;
    public DateRange(int start, int end) { Start = start; End = end; }
    public bool Equals(DateRange other) => Start == other.Start && End == other.End;
    public override bool Equals(object obj) => obj is DateRange d && Equals(d);
    public override int GetHashCode() => HashCode.Combine(Start, End);
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new DateRange(1, 5).Equals(new DateRange(1, 5)));
        Console.WriteLine(new DateRange(1, 5).Equals(new DateRange(1, 6)));
    }
}

จับคู่กับตัวดำเนินการ

ใช้ IEquatable<T> ร่วมกับ == และ != เพื่อให้ผู้ใช้เปรียบเทียบได้ด้วยไวยากรณ์ทั้งสองแบบ โดยมีการเปรียบเทียบที่มีชนิดข้อมูลชัดเจนแบบเดียวกันอยู่เบื้องหลัง

using System;

public struct Money : IEquatable<Money>
{
    public decimal Amount;
    public Money(decimal a) { Amount = a; }
    public bool Equals(Money other) => Amount == other.Amount;
    public override bool Equals(object obj) => obj is Money m && Equals(m);
    public override int GetHashCode() => Amount.GetHashCode();
    public static bool operator ==(Money a, Money b) => a.Equals(b);
    public static bool operator !=(Money a, Money b) => !a.Equals(b);
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Money(9.99m) == new Money(9.99m));
    }
}

ระเบียนนำสิ่งนี้ไปใช้โดยอัตโนมัติ

record ของ C# จะสร้าง IEquatable<T>, Equals ที่อิงค่า และ GetHashCode ให้โดยอัตโนมัติ เมื่อคุณต้องการเพียงการตรวจสอบความเท่ากันโดยอิงค่า ระเบียนจะช่วยลดโค้ดส่วนเกินได้

using System;

public record Point(int X, int Y);

public class Program
{
    public static void Main()
    {
        var a = new Point(1, 2);
        var b = new Point(1, 2);
        Console.WriteLine(a.Equals(b));
        Console.WriteLine(a == b);
    }
}

เมื่อใดควรนำไปใช้ด้วยตนเอง

นำ IEquatable<T> ไปใช้ด้วยตนเองเมื่อคุณต้องการกฎการตรวจสอบความเท่ากันแบบกำหนดเอง เช่น ชื่อที่ไม่คำนึงถึงตัวพิมพ์เล็กใหญ่ หรือการละเว้นบางฟิลด์ ซึ่งระเบียนไม่สามารถแสดงได้โดยตรง

using System;

public class CaseInsensitiveTag : IEquatable<CaseInsensitiveTag>
{
    public string Name;
    public CaseInsensitiveTag(string name) { Name = name; }
    public bool Equals(CaseInsensitiveTag other)
        => other != null && string.Equals(Name, other.Name, StringComparison.OrdinalIgnoreCase);
    public override bool Equals(object obj) => Equals(obj as CaseInsensitiveTag);
    public override int GetHashCode() => Name?.ToLowerInvariant().GetHashCode() ?? 0;
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new CaseInsensitiveTag("Red").Equals(new CaseInsensitiveTag("RED")));
    }
}

ลองทำด้วยตนเอง

นำ IEquatable<T> ไปใช้กับชนิดข้อมูลอ้างอิงขนาดเล็ก และให้ทุกเส้นทางการตรวจสอบความเท่ากันเรียกผ่านเมธอดที่มีชนิดข้อมูลชัดเจน

using System;
using System.Collections.Generic;

public class Coordinate : IEquatable<Coordinate>
{
    public int Lat, Lng;
    public Coordinate(int lat, int lng) { Lat = lat; Lng = lng; }
    public bool Equals(Coordinate other) => other != null && other.Lat == Lat && other.Lng == Lng;
    public override bool Equals(object obj) => Equals(obj as Coordinate);
    public override int GetHashCode() => HashCode.Combine(Lat, Lng);
}

public class Program
{
    public static void Main()
    {
        var set = new HashSet<Coordinate> { new Coordinate(10, 20) };
        Console.WriteLine(set.Contains(new Coordinate(10, 20)));
    }
}

ตรวจสอบอย่างรวดเร็ว

ทบทวนประโยชน์ของ IEquatable

สรุปทบทวน

IEquatable<T> มอบการตรวจสอบความเท่ากันที่ปลอดภัยด้านชนิดข้อมูล

  • จัดเตรียม Equals(T other) ซึ่งช่วยหลีกเลี่ยงการบรรจุค่าสำหรับโครงสร้างและการแปลงชนิดสำหรับคลาส
  • คอลเลกชันจะเลือกใช้สิ่งนี้เพื่อการค้นหาที่ถูกต้องและมีประสิทธิภาพ
  • ให้ object.Equals และตัวดำเนินการเรียกผ่านเมธอดที่มีชนิดข้อมูลชัดเจน
  • ระเบียนนำสิ่งนี้ไปใช้โดยอัตโนมัติ ส่วนกฎแบบกำหนดเองควรนำไปใช้ด้วยตนเอง

คำถามที่พบบ่อย

บทเรียน “การนำ IEquatable ไปใช้” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การนำ IEquatable ไปใช้” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C# Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การนำ IEquatable ไปใช้”

จัดเตรียมการตรวจสอบความเท่ากันที่ปลอดภัยต่อชนิดข้อมูลด้วย Equals คุณปฏิบัติ C# Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C# Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน C# Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “การนำ IEquatable ไปใช้” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน C# Academy นี้ได้ไหม

ได้ บทเรียน C# Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การนำ IEquatable ไปใช้
  2. การเขียนทับ GetHashCode
  3. การนำ IComparable ไปใช้
  4. IComparer สำหรับการเรียงลำดับแบบกำหนดเอง
← กลับไปที่ C# Academy