การโอเวอร์โหลดตัวดำเนินการเปรียบเทียบ
นำ ==, != และตัวดำเนินการจัดลำดับไปใช้
การโอเวอร์โหลดตัวดำเนินการเปรียบเทียบ เป็นบทเรียน 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การโอเวอร์โหลดตัวดำเนินการเลขคณิต
- การโอเวอร์โหลดตัวดำเนินการเปรียบเทียบ
- การแปลงที่ผู้ใช้กำหนด
- แนวทางปฏิบัติที่ดีในการโอเวอร์โหลดตัวดำเนินการ