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

การโอเวอร์โหลดตัวดำเนินการเปรียบเทียบ

นำ ==, != และตัวดำเนินการจัดลำดับไปใช้

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

ตัวดำเนินการเปรียบเทียบและความเท่ากัน

เมื่อคุณโอเวอร์โหลด == คุณต้องโอเวอร์โหลด != ด้วย และควรเขียนทับ Equals กับ GetHashCode เพื่อให้รูปแบบการตรวจสอบความเท่ากันทั้งหมดสอดคล้องกัน C# จะบังคับให้จับคู่ตัวดำเนินการเหล่านี้ตั้งแต่เวลาคอมไพล์

การโอเวอร์โหลด == และ !=

คอมไพเลอร์กำหนดให้ == และ != ต้องนิยามพร้อมกัน แต่ละตัวส่งคืนค่า bool ที่บอกว่าตัวถูกดำเนินการถือว่าเท่ากันหรือไม่

using System;

public struct Point
{
    public int X, Y;
    public Point(int x, int y) { X = x; Y = y; }

    public static bool operator ==(Point a, Point b) => a.X == b.X && a.Y == b.Y;
    public static bool operator !=(Point a, Point b) => !(a == b);

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

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Point(1, 2) == new Point(1, 2));
        Console.WriteLine(new Point(1, 2) != new Point(3, 4));
    }
}

เขียนทับ Equals ด้วยเสมอ

ตัวดำเนินการจะถูกเลือกโดยชนิดข้อมูลแบบคงที่ตั้งแต่เวลาคอมไพล์ แต่ Equals เป็นเสมือนและถูกใช้โดยคอลเลกชัน ให้เขียนทับ Equals เพื่อให้พจนานุกรมและ List.Contains ให้ผลสอดคล้องกับ ==

using System;

public struct Point
{
    public int X, Y;
    public Point(int x, int y) { X = x; Y = y; }
    public static bool operator ==(Point a, Point b) => a.X == b.X && a.Y == b.Y;
    public static bool operator !=(Point a, Point b) => !(a == b);
    public override bool Equals(object obj) => obj is Point p && this == p;
    public override int GetHashCode() => HashCode.Combine(X, Y);
}

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

GetHashCode ต้องสอดคล้องกับความเท่ากัน

หากค่าสองค่าเท่ากัน ค่าทั้งสองต้องส่งคืนรหัสแฮชเดียวกัน มิฉะนั้นคอลเลกชันที่ใช้แฮช เช่น Dictionary และ HashSet จะทำงานไม่ถูกต้อง

using System;
using System.Collections.Generic;

public struct Point
{
    public int X, Y;
    public Point(int x, int y) { X = x; Y = y; }
    public static bool operator ==(Point a, Point b) => a.X == b.X && a.Y == b.Y;
    public static bool operator !=(Point a, Point b) => !(a == b);
    public override bool Equals(object obj) => obj is Point p && this == p;
    public override int GetHashCode() => HashCode.Combine(X, Y);
}

public class Program
{
    public static void Main()
    {
        var set = new HashSet<Point> { new Point(1, 2) };
        Console.WriteLine(set.Contains(new Point(1, 2)));
    }
}

ตัวดำเนินการเรียงลำดับ < และ >

คุณสามารถโอเวอร์โหลดตัวดำเนินการเชิงสัมพันธ์ได้เช่นกัน เช่นเดียวกับความเท่ากัน < และ > ต้องนิยามพร้อมกัน และ <= กับ >= ก็เช่นกัน

using System;

public struct Weight
{
    public int Grams;
    public Weight(int g) { Grams = g; }

    public static bool operator <(Weight a, Weight b) => a.Grams < b.Grams;
    public static bool operator >(Weight a, Weight b) => a.Grams > b.Grams;

    public override string ToString() => Grams + "g";
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Weight(100) < new Weight(200));
        Console.WriteLine(new Weight(300) > new Weight(200));
    }
}

ความเท่ากันสำหรับชนิดข้อมูลแบบอ้างอิง

สำหรับคลาส ความเท่ากันของค่าหมายถึงการเปรียบเทียบฟิลด์ ไม่ใช่การอ้างอิง โปรดจัดการ null อย่างระมัดระวังเพื่อไม่ให้เกิดข้อผิดพลาดภายในตัวดำเนินการ

using System;

public class Person
{
    public string Name;
    public Person(string name) { Name = name; }

    public static bool operator ==(Person a, Person b)
    {
        if (ReferenceEquals(a, b)) return true;
        if (a is null || b is null) return false;
        return a.Name == b.Name;
    }
    public static bool operator !=(Person a, Person b) => !(a == b);
    public override bool Equals(object obj) => this == (obj as Person);
    public override int GetHashCode() => Name?.GetHashCode() ?? 0;
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Person("Ann") == new Person("Ann"));
    }
}

ความสอดคล้องระหว่างรูปแบบต่าง ๆ

เส้นทางการตรวจสอบความเท่ากันทั้งหมดควรให้ผลตรงกัน ได้แก่ ==, Equals และรหัสแฮช ให้สร้าง == โดยอาศัย Equals (หรือกลับกัน) เพื่อให้มีแหล่งอ้างอิงความจริงเพียงแห่งเดียว

using System;

public struct 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 static bool operator ==(Id a, Id b) => a.Equals(b);
    public static bool operator !=(Id a, Id b) => !a.Equals(b);
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Id(7) == new Id(7));
        Console.WriteLine(new Id(7).Equals(new Id(8)));
    }
}

ตัวดำเนินการกับ Equals ในคอลเลกชัน

การค้นหาใน List ใช้ Equals ไม่ใช่ == เนื่องจากทำงานกับการอ้างอิง object หากคุณโอเวอร์โหลดเฉพาะ == และลืม Equals การค้นหาจะใช้เอกลักษณ์ของการอ้างอิงและอาจล้มเหลว

using System;
using System.Collections.Generic;

public struct Tag
{
    public string Name;
    public Tag(string name) { Name = name; }
    public override bool Equals(object obj) => obj is Tag t && t.Name == Name;
    public override int GetHashCode() => Name?.GetHashCode() ?? 0;
    public static bool operator ==(Tag a, Tag b) => a.Equals(b);
    public static bool operator !=(Tag a, Tag b) => !a.Equals(b);
}

public class Program
{
    public static void Main()
    {
        var list = new List<Tag> { new Tag("red"), new Tag("blue") };
        Console.WriteLine(list.Contains(new Tag("blue")));
    }
}

การปิดคำเตือนของคอมไพเลอร์อย่างถูกต้อง

การเขียนทับ Equals และ GetHashCode ควบคู่กับตัวดำเนินการไม่ใช่เพียงมารยาทเท่านั้น คอมไพเลอร์จะแสดงคำเตือนหากคุณโอเวอร์โหลด == โดยไม่เขียนทับ Equals การทำทั้งสองอย่างจะลบคำเตือนและป้องกันข้อผิดพลาด

using System;

public struct Cell
{
    public int Row, Col;
    public Cell(int r, int c) { Row = r; Col = c; }
    public override bool Equals(object obj) => obj is Cell c && c.Row == Row && c.Col == Col;
    public override int GetHashCode() => HashCode.Combine(Row, Col);
    public static bool operator ==(Cell a, Cell b) => a.Equals(b);
    public static bool operator !=(Cell a, Cell b) => !a.Equals(b);
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Cell(0, 0) == new Cell(0, 0));
    }
}

ประกอบทุกอย่างเข้าด้วยกัน

ชนิดข้อมูลที่รองรับการตรวจสอบความเท่ากันอย่างเหมาะสมจะนิยาม ==, != เขียนทับ Equals และ GetHashCode แล้วให้ทั้งหมดใช้การเปรียบเทียบเดียวกัน นี่คือมาตรฐานสูงสุดสำหรับชนิดข้อมูลที่มีลักษณะเหมือนค่า

using System;
using System.Collections.Generic;

public struct Color
{
    public int R, G, B;
    public Color(int r, int g, int b) { R = r; G = g; B = b; }
    public override bool Equals(object obj) => obj is Color c && c.R == R && c.G == G && c.B == B;
    public override int GetHashCode() => HashCode.Combine(R, G, B);
    public static bool operator ==(Color a, Color b) => a.Equals(b);
    public static bool operator !=(Color a, Color b) => !a.Equals(b);
}

public class Program
{
    public static void Main()
    {
        var dict = new Dictionary<Color, string> { [new Color(255, 0, 0)] = "red" };
        Console.WriteLine(dict[new Color(255, 0, 0)]);
    }
}

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

สร้างโครงสร้างข้อมูลที่รองรับการตรวจสอบความเท่ากันอย่างสอดคล้องครบถ้วน และตรวจสอบว่าสามารถใช้เป็นคีย์ของพจนานุกรมและใช้กับตัวดำเนินการ == ได้พร้อมกัน

using System;
using System.Collections.Generic;

public struct GridPos
{
    public int Row, Col;
    public GridPos(int r, int c) { Row = r; Col = c; }
    public override bool Equals(object obj) => obj is GridPos p && p.Row == Row && p.Col == Col;
    public override int GetHashCode() => HashCode.Combine(Row, Col);
    public static bool operator ==(GridPos a, GridPos b) => a.Equals(b);
    public static bool operator !=(GridPos a, GridPos b) => !a.Equals(b);
}

public class Program
{
    public static void Main()
    {
        var grid = new Dictionary<GridPos, string> { [new GridPos(1, 1)] = "player" };
        Console.WriteLine(new GridPos(1, 1) == new GridPos(1, 1));
        Console.WriteLine(grid[new GridPos(1, 1)]);
    }
}

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

ทบทวนกฎสำหรับการโอเวอร์โหลดความเท่ากัน

สรุปทบทวน

การโอเวอร์โหลดตัวดำเนินการเปรียบเทียบต้องมีความสอดคล้อง

  • == และ != ต้องนิยามพร้อมกัน เช่นเดียวกับ </>
  • เขียนทับ Equals และ GetHashCode ให้สอดคล้องกับ ==
  • ค่าที่เท่ากันต้องใช้รหัสแฮชเดียวกัน
  • ให้การตรวจสอบความเท่ากันทั้งหมดผ่านเมธอดเปรียบเทียบเดียวกันเพื่อป้องกันความคลาดเคลื่อน

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

บทเรียน “การโอเวอร์โหลดตัวดำเนินการเปรียบเทียบ” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “การโอเวอร์โหลดตัวดำเนินการเปรียบเทียบ”

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

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

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

บทเรียน “การโอเวอร์โหลดตัวดำเนินการเปรียบเทียบ” ใช้เวลานานแค่ไหน

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

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

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

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

  1. การโอเวอร์โหลดตัวดำเนินการเลขคณิต
  2. การโอเวอร์โหลดตัวดำเนินการเปรียบเทียบ
  3. การแปลงที่ผู้ใช้กำหนด
  4. แนวทางปฏิบัติที่ดีในการโอเวอร์โหลดตัวดำเนินการ
← กลับไปที่ C# Academy