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

การนำ 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

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

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