تنفيذ IComparable
عرّفوا ترتيبًا طبيعيًا باستخدام CompareTo
تنفيذ IComparable درس مجاني في C# Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 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));
}
}المقارنة حسب حقل أساسي
بالنسبة إلى الفئة، اختر الحقل الذي يحدد ترتيبها الطبيعي. في هذا المثال، يُرتب الأشخاص حسب العمر، مع تفويض المقارنة إلى 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
حتى من دون الترتيب في المكان، يستطيع OrderBy في LINQ استخدام نوعك القابل للمقارنة عبر محدد مفتاح، لينتج عرضًا مرتبًا بشكل كسول.
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» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C# Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C# Academy 4 دروس في المجموع.
ماذا ستتعلم في «تنفيذ IComparable»؟
عرّفوا ترتيبًا طبيعيًا باستخدام CompareTo تتمرن على C# Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ C# Academy؟
لا تُشترط خبرة سابقة. C# Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.
كم من الوقت يستغرق درس «تنفيذ IComparable»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس C# Academy هذا؟
نعم. كل درس في C# Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- تنفيذ IEquatable
- تجاوز GetHashCode
- تنفيذ IComparable
- IComparer للفرز المخصّص