การนำ IComparable ไปใช้
กำหนดลำดับการเรียงตามธรรมชาติด้วย CompareTo
การนำ IComparable ไปใช้ เป็นบทเรียน C# Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C# Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน
การจัดลำดับด้วย IComparable<T>
IComparable<T> กำหนดลำดับตามธรรมชาติให้ชนิดข้อมูลผ่านเมธอดเดียวคือ CompareTo เมื่อทำการนำไปใช้แล้ว ชนิดข้อมูลของคุณจะสามารถจัดเรียงด้วย Array.Sort, List.Sort และคอลเลกชันที่มีการจัดลำดับได้
ข้อตกลงของ CompareTo
CompareTo จะส่งคืนจำนวนลบหากอินสแตนซ์นี้น้อยกว่าอีกอินสแตนซ์ ส่งคืนศูนย์หากเท่ากัน และส่งคืนจำนวนบวกหากมากกว่า การเปรียบเทียบค่าพื้นฐานมักนำไปใช้ในลักษณะนี้ได้โดยตรง
using System;
public struct Weight : IComparable<Weight>
{
public int Grams;
public Weight(int g) { Grams = g; }
public int CompareTo(Weight other) => Grams.CompareTo(other.Grams);
public override string ToString() => Grams + "g";
}
public class Program
{
public static void Main()
{
Console.WriteLine(new Weight(100).CompareTo(new Weight(200)));
Console.WriteLine(new Weight(200).CompareTo(new Weight(200)));
Console.WriteLine(new Weight(300).CompareTo(new Weight(200)));
}
}การจัดเรียงรายการ
เมื่อชนิดข้อมูลสามารถเปรียบเทียบได้แล้ว List<T>.Sort() จะจัดเรียงชนิดข้อมูลนั้นโดยใช้ CompareTo โดยไม่ต้องมีอาร์กิวเมนต์เพิ่มเติม
using System;
using System.Collections.Generic;
public struct Weight : IComparable<Weight>
{
public int Grams;
public Weight(int g) { Grams = g; }
public int CompareTo(Weight other) => Grams.CompareTo(other.Grams);
public override string ToString() => Grams + "g";
}
public class Program
{
public static void Main()
{
var list = new List<Weight> { new Weight(300), new Weight(100), new Weight(200) };
list.Sort();
Console.WriteLine(string.Join(", ", list));
}
}การเปรียบเทียบตามฟิลด์หลัก
สำหรับคลาส ให้เลือกฟิลด์ที่กำหนดลำดับตามธรรมชาติของคลาส ในที่นี้ people จะถูกจัดลำดับตามอายุ โดยส่งต่อการทำงานให้ int.CompareTo
using System;
using System.Collections.Generic;
public class Person : IComparable<Person>
{
public string Name;
public int Age;
public Person(string name, int age) { Name = name; Age = age; }
public int CompareTo(Person other) => Age.CompareTo(other.Age);
public override string ToString() => Name + "(" + Age + ")";
}
public class Program
{
public static void Main()
{
var people = new List<Person> { new Person("Ann", 30), new Person("Bo", 20) };
people.Sort();
Console.WriteLine(string.Join(", ", people));
}
}การใช้ฟิลด์หลายรายการเพื่อตัดสินกรณีเสมอ
เมื่อคีย์หลักมีค่าเท่ากัน ให้เปรียบเทียบฟิลด์รอง คำนวณผลการเปรียบเทียบครั้งแรก และทำการเปรียบเทียบถัดไปเฉพาะเมื่อผลลัพธ์เป็นศูนย์เท่านั้น
using System;
using System.Collections.Generic;
public class Person : IComparable<Person>
{
public string Name;
public int Age;
public Person(string name, int age) { Name = name; Age = age; }
public int CompareTo(Person other)
{
int byAge = Age.CompareTo(other.Age);
return byAge != 0 ? byAge : string.Compare(Name, other.Name, StringComparison.Ordinal);
}
public override string ToString() => Name + "(" + Age + ")";
}
public class Program
{
public static void Main()
{
var people = new List<Person> { new Person("Zoe", 30), new Person("Ann", 30) };
people.Sort();
Console.WriteLine(string.Join(", ", people));
}
}การจัดเรียงอาร์เรย์
Array.Sort อาศัย IComparable<T> เช่นกัน ตรรกะการเปรียบเทียบเดียวกันนี้จึงใช้ได้กับอาร์เรย์ รายการ และโครงสร้างที่มีการจัดลำดับ
using System;
public struct Score : IComparable<Score>
{
public int Points;
public Score(int p) { Points = p; }
public int CompareTo(Score other) => Points.CompareTo(other.Points);
public override string ToString() => Points.ToString();
}
public class Program
{
public static void Main()
{
var scores = new[] { new Score(50), new Score(10), new Score(30) };
Array.Sort(scores);
Console.WriteLine(string.Join(", ", (object[])scores));
}
}ลำดับจากมากไปน้อย
หากต้องการย้อนลำดับ ให้กลับผลการเปรียบเทียบด้วยการสลับตัวถูกดำเนินการของ CompareTo วิธีนี้เป็นวิธีที่สะอาดในการจัดเรียงจากค่าสูงไปค่าต่ำโดยไม่ต้องมีตัวเปรียบเทียบแยกต่างหาก
using System;
using System.Collections.Generic;
public struct Score : IComparable<Score>
{
public int Points;
public Score(int p) { Points = p; }
// Reversed: higher points come first
public int CompareTo(Score other) => other.Points.CompareTo(Points);
public override string ToString() => Points.ToString();
}
public class Program
{
public static void Main()
{
var list = new List<Score> { new Score(10), new Score(50), new Score(30) };
list.Sort();
Console.WriteLine(string.Join(", ", list));
}
}ชนิดข้อมูลที่เปรียบเทียบได้และตรวจสอบความเท่ากันได้
หาก CompareTo ส่งคืนศูนย์ รายการเหล่านั้นจะถือว่าเท่ากันในแง่ของการจัดลำดับ ทำให้สอดคล้องกับ Equals เพื่อให้การจัดเรียงและการตรวจสอบความเท่ากันให้ผลตรงกัน
using System;
public struct Version : IComparable<Version>, IEquatable<Version>
{
public int Major, Minor;
public Version(int major, int minor) { Major = major; Minor = minor; }
public int CompareTo(Version other)
{
int byMajor = Major.CompareTo(other.Major);
return byMajor != 0 ? byMajor : Minor.CompareTo(other.Minor);
}
public bool Equals(Version other) => CompareTo(other) == 0;
public override bool Equals(object obj) => obj is Version v && Equals(v);
public override int GetHashCode() => HashCode.Combine(Major, Minor);
}
public class Program
{
public static void Main()
{
Console.WriteLine(new Version(1, 2).CompareTo(new Version(1, 5)));
Console.WriteLine(new Version(2, 0).Equals(new Version(2, 0)));
}
}การใช้การเปรียบเทียบใน LINQ OrderBy
แม้จะไม่ได้จัดเรียงข้อมูลในตำแหน่งเดิม LINQ OrderBy ก็สามารถใช้ชนิดข้อมูลที่เปรียบเทียบได้ของคุณผ่านตัวเลือกคีย์ และสร้างมุมมองที่จัดเรียงแล้วแบบประเมินผลเมื่อใช้งาน
using System;
using System.Collections.Generic;
using System.Linq;
public struct Weight : IComparable<Weight>
{
public int Grams;
public Weight(int g) { Grams = g; }
public int CompareTo(Weight other) => Grams.CompareTo(other.Grams);
public override string ToString() => Grams + "g";
}
public class Program
{
public static void Main()
{
var items = new List<Weight> { new Weight(300), new Weight(100) };
foreach (var w in items.OrderBy(x => x))
Console.WriteLine(w);
}
}ชนิดข้อมูลโดเมนที่เรียงลำดับได้
การนำ IComparable<T> ไปใช้ทำให้แนวคิดของโดเมนกลายเป็นสิ่งที่ทั้งเฟรมเวิร์กสามารถจัดลำดับได้ ในที่นี้ งานจะถูกเรียงตามลำดับความสำคัญ แล้วจึงตามชื่อ
using System;
using System.Collections.Generic;
public class TaskItem : IComparable<TaskItem>
{
public string Name;
public int Priority;
public TaskItem(string name, int priority) { Name = name; Priority = priority; }
public int CompareTo(TaskItem other)
{
int byPriority = Priority.CompareTo(other.Priority);
return byPriority != 0 ? byPriority : string.Compare(Name, other.Name, StringComparison.Ordinal);
}
public override string ToString() => Priority + ":" + Name;
}
public class Program
{
public static void Main()
{
var tasks = new List<TaskItem>
{
new TaskItem("deploy", 2), new TaskItem("build", 1), new TaskItem("test", 1)
};
tasks.Sort();
Console.WriteLine(string.Join(", ", tasks));
}
}ลองทำด้วยตนเอง
สร้างชนิดข้อมูลที่เปรียบเทียบได้โดยมีหลายฟิลด์ แล้วเรียงรายการของชนิดข้อมูลนั้น ลำดับตามธรรมชาติจะได้จาก CompareTo โดยไม่ต้องมีอาร์กิวเมนต์เพิ่มเติม
using System;
using System.Collections.Generic;
public class Card : IComparable<Card>
{
public int Rank;
public string Suit;
public Card(int rank, string suit) { Rank = rank; Suit = suit; }
public int CompareTo(Card other)
{
int byRank = Rank.CompareTo(other.Rank);
return byRank != 0 ? byRank : string.Compare(Suit, other.Suit, StringComparison.Ordinal);
}
public override string ToString() => Rank + Suit;
}
public class Program
{
public static void Main()
{
var hand = new List<Card>
{
new Card(10, "H"), new Card(2, "S"), new Card(10, "C")
};
hand.Sort();
Console.WriteLine(string.Join(", ", hand));
}
}ตรวจสอบอย่างรวดเร็ว
ทบทวนข้อตกลงของ CompareTo
สรุปทบทวน
IComparable<T> กำหนดลำดับตามธรรมชาติผ่าน CompareTo
- ค่าลบ ศูนย์ และค่าบวก หมายถึงน้อยกว่า เท่ากัน และมากกว่า
- ทำให้ใช้
List.Sort,Array.Sortและคอลเลกชันที่เรียงลำดับได้ - ใช้ฟิลด์รองเปรียบเทียบเพื่อตัดสินกรณีที่ค่าเท่ากัน
- ทำให้
CompareTo == 0สอดคล้องกับEquals
คำถามที่พบบ่อย
บทเรียน “การนำ IComparable ไปใช้” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การนำ IComparable ไปใช้” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C# Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การนำ IComparable ไปใช้”
กำหนดลำดับการเรียงตามธรรมชาติด้วย CompareTo คุณปฏิบัติ C# Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C# Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน C# Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “การนำ IComparable ไปใช้” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน C# Academy นี้ได้ไหม
ได้ บทเรียน C# Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การนำ IEquatable ไปใช้
- การเขียนทับ GetHashCode
- การนำ IComparable ไปใช้
- IComparer สำหรับการเรียงลำดับแบบกำหนดเอง