حسین احمدی
بنیانگذار توسینسو و برنامه نویس و توسعه دهنده ارشد وب

مرتب سازی اشیا در C# با اینترفیس های IComparable و IComparer

خیلی وقت ها، اشیاء ای که ایجاد می کنیم می بایست قابلیت مرتب سازی داشته باشند. برای مثال، کلاس List~T، متدی دارد به نام Sort که لیست را مرتب می کند. این متد بر اساس مکانیزم مرتب سازی تعریف شده برای نوع T انتخاب شده اقدام به مرتب سازی لیست می کند، همچنین امکان مشخص کردن مکانیزم مرتب سازی برای لیست نیز وجود دارد. در ابتدا با یک مثال ساده شروع می کنیم، کد زیر لیستی از اعداد را به صورت صعودی مرتب می کند:

دوره های شبکه، برنامه نویسی، مجازی سازی، امنیت، نفوذ و ... با برترین های ایران
var numbers = new List<int> {2, 1, 3, 7, 4, 6, 5};
numbers.Sort();

foreach (var number in numbers)
{
    Console.WriteLine(number);
}

حال، فرض کنید کلاسی به صورت زیر تعریف کردیم:

public class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public override string ToString()
    {
        return string.Format("{0}: {1} {2}", Id, FirstName, LastName);
    }
}

بوسیله کد زیر قصد داریم لیستی ایجاد کرده و آن را مرتب کنیم:

var persons = new List<Person>()
{
    new Person() {Id = 2, FirstName = "Hossein", LastName = "Ahmadi"},
    new Person() {Id = 1, FirstName = "Mohammad", LastName = "Nasiri"},
    new Person() {Id = 3, FirstName = "Mehdi", LastName = "Adelifar"}
};

persons.Sort();

foreach (var person in persons)
{
    Console.WriteLine(person);
}

با اجرای کد بالا، قسمتی که متد Sort فراخوانی می شود باعث بروز خطا می شود. به این دلیل که برای کلاس Person هیچ مکانیزم مرتب سازی تعریف نشده است. برای اینکه قابلیت مرتب سازی به کلاس Person اضافه شود، می بایست اینترفیس IComparer را برای آن پیاده سازی کنیم، کد کلاس Person را به صورت زیر تغییر می دهیم:

public class Person : IComparable<Person>
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public int CompareTo(Person other)
    {
        if (Id > other.Id)
            return 1;
        if (Id == other.Id)
            return 0;
        else return -1;
    }

    public override string ToString()
    {
        return string.Format("{0}: {1} {2}", Id, FirstName, LastName);
    }
}

با اعمال تغییرات بالا و فراخوانی متد Sort، لیست ما بر اساس خصوصیت Id مرتب می شود. در حقیقت، کاری که متد CompareTo انجام می دهد، مکانیزم مرتب سازی پیش فرض کلاس Person است. نوع بازگشتی متد CompareTo از نوع int است، به این صورت که:

  1. اگر مقدار اولی از مقدار دومی بزرگتر باشد، عدد 1 برگردانده می شود
  2. اگر مقدار اولی با مقدار دومی برابر باشد، عدد 0 برگردانده می شود
  3. و اگر مقدار اولی از مقدار دومی کوچکتر باشد، عدد 1- برگردانده می شود

تمامی نوع های داده اولیه در سی شارپ، به صورت پیش فرض اینترفیس IComparable را پیاده سازی کرده اند، اما برای کلاس های تعریف شده در برنامه می بایست این پیاده سازی توسط برنامه نویس انجام شود. متد Sort که در بالا با آن آشنا شدیم، علاوه بر حالت پیش فرض که هیچ پارامتری دریافت نکرده و بر اساس مکانیزم پیش فرض مرتب سازی اعضاء لیست، کار مرتب سازی را انجام می دهد، یک overload دیگر نیز دارد که شئ ای از نوع IComparer~T قبول می کند، در حقیقت شما می توانید شئ جدیدی تعریف کنید که مکانیزم مرتب سازی دیگری را تعریف می کند، کلاس دیگری با نام PersonNameComparer به صورت زیر ایجاد می کنیم:

public class PersonNameComparer : IComparer<Person>
{
    public int Compare(Person x, Person y)
    {
        return (x.FirstName + " " + x.LastName).CompareTo(y.FirstName + " " + y.LastName);
    }
}

همانطور که در کد بالا مشاهده می کنید، به جای نوشتن if ها، از متد CompareTo که به صورت پیش فرض برای نوع داده رشته تعریف شده است استفاده کردیم، حال متد Sort را به صورت زیر تغییر می دهیم:

persons.Sort(new PersonNameComparer());

با تغییر بالا، لیست persons بر اساس ترکیب نام و نام خانوادگی مرتب خواهد شد. قابلیت مرتب سازی کاربرد زیادی در نوشتن برنامه ها دارد و توصیه می شود حتماً از مکانیزم های استاندارد زبان سی شارپ، یعنی استفاده از interface ها این کار انجام شود. امیدوارم که این مطلب مورد توجه دوستان عزیز قرار گرفته باشد. ITPRO باشید


حسین احمدی
حسین احمدی

بنیانگذار توسینسو و برنامه نویس و توسعه دهنده ارشد وب

حسین احمدی ، بنیانگذار TOSINSO ، توسعه دهنده وب و برنامه نویس ، بیش از 12 سال سابقه فعالیت حرفه ای در سطح کلان ، مشاور ، مدیر پروژه و مدرس نهادهای مالی و اعتباری ، تخصص در پلتفرم دات نت و زبان سی شارپ ، طراحی و توسعه وب ، امنیت نرم افزار ، تحلیل سیستم های اطلاعاتی و داده کاوی ...

نظرات