PDA

View Full Version : فرق اینترفیس های IComparer و IComparable چیست؟



hasan1896
یک شنبه 28 آذر 1389, 22:46 عصر
با سلام خدمت اساتید محترم میخام بدونم دقیقا کار این اینترفیسها چیه و چه تفاوتی باهم دارند؟ یه مثال کاربردی و ساده و قابل فهم هم اگه داشتید بزارید :لبخند:

sokote_bi_payan
سه شنبه 30 آذر 1389, 10:39 صبح
به نام خدا
سلام
از این دو تا بیشتر برای مرتب سازی استفاده می شه

sokote_bi_payan
سه شنبه 30 آذر 1389, 10:43 صبح
هر کلاسی که با IComparable پیاده سازی بشه قابلیت مقایسه کردن خواهد داشت به این معنی که شما می تونید یه نمونه (شی) از این کلاس تون رو با نمونه های دیگه از همین نوع مقایسه کنید.

devhandler
سه شنبه 30 آذر 1389, 10:45 صبح
اینترفیس IComparer متد Compare رو پیاده سازی میکنه که دو تا Object میگیره، اما IComparable متد CompareTo رو پیاده سازی میکنه که یک Object میگیره و با Instance خود کلاس مقایسه میکنه، اینترفیس IComparer با متدهای Array.Sort و Array.BinarySearch کار میکنه.

sokote_bi_payan
سه شنبه 30 آذر 1389, 10:54 صبح
ولی به نظر من به جای اینکه از این روش استفاده می کنیم خیلی ساده تر و راحت تر میشه از LINQ بهره گرفت. باز دوستان و اساتید کاش بیان و توضیح بدن

sokote_bi_payan
سه شنبه 30 آذر 1389, 10:56 صبح
Suppose you have a class Dog, and an ArrayList, List, of Dogs. You wish to
sort List by ageOfDog. You would have Dog implement the interface
IComparable. The implementation would cast the parameter in the CompareTo
method to a Dog, and return a value based on how this.ageOfDog compared to
((Dog)(obj)).ageOfDog). Then to sort the List, you could just invoke
List.Sort().

But suppose in another part of the application you would like to sort the
same List by nameOfDog. You have already "used up" the IComparable
interface that Sort uses. So, you can either set up a new class that
inherits from IComparer, or (if this is the only additional sort you need),
have Dog implement the IComparer interface too.
Then in the Compare method, which has two parameters, you would cast each to
a Dog and return a value based upon how the nameOfDog compares. Then to
invoke a sort by nameOfDog you would just say List.Sort(this) (or
List.Sort(someObjectThatImplementsIComparer)).

hasan1896
سه شنبه 30 آذر 1389, 11:49 صبح
با تشکر ولی اگه میشد مطلب انگلیسی رو به فارسی ترجمه میکردی بهتر بود. من میدونم که هر کدوم چطور پیاده سازی میشن ولی میخام بدونم کجا از کدومشون استفاده میکنن؟؟؟؟

irpersian20
چهارشنبه 11 دی 1392, 09:16 صبح
سلام
به اجبار باید این تاپیک بالا بیاد.
این طور که مشخص هست CompareTo هم میتواند 2 آبجکت بگیرد.

partovinia
چهارشنبه 06 اسفند 1393, 13:59 عصر
سلام به شما دوستان گرامی .من نوشته های شما رو خوندم ؛ ولی بیشتر گیج شدم .میشه کامل تر وبیشتر توضیح بدین؟ واقعا کی باید از کدوم استفاده کنیم ؟ یعنی هر وقت خواستیم توی کلاسی کار sort رو انجام بدیم باید از این اینترفیس ها استفاده بشه ؟ با تشکر

یونس ابراهیمی
شنبه 09 اسفند 1393, 09:04 صبح
دو رابط مفید برای مقایسه اشیایی که توسط کاربر تعریف شده اند وجود دارد. این دو رابط IComparable<T> و IComparer<T> می باشند.


رابط <IComparable<T

رابط IComparable<T> در یک کلاس پیاده سازی می شود و اجازه می دهد کلاس یا شی ایجاد شده از کلاس با اشیاء دیگر از همین کلاس مقایسه شوند. به این نکته توجه کنید که نسخه های غیر جنریک این دو رابط نیز وجود دارد ولی کار کردن با نسخه های جنریک آنها بسیار راحت تر بوده و شما نیاز به تبدیل برای مقایسه اشیاء ندارید.

حال به نحوه استفاده از رابط IComparable<T> می پردازیم. در مثال زیر یک کلاس نشان داده شده است که رابط IComparable<T> را پیاده سازی می کند:


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

public int CompareTo(Person other)
{
if (this.Age > other.Age)
return 1;
else if (this.Age < other.Age)
return -1;
else
return 0;
}
}


وقتی که یک کلاس از رابط IComparable<T> استفاده می کند، لازم است که تنها متد آن یعنی متد CompareTo() را نیز پیاده سازی کند. متد CompareTo() یک مقدار صحیح را بر می گرداند. این متد همچنین یک آرگومان قبول می کند که همان شیی است که قرار است با شی جاری مقایسه شود. در داخل متد CompareTo() در مثال بالا ما سن (age) شخص فعلی را با سن شخص دیگر مقایسه کرده ایم. طبق قرارداد اگر سن شخص مورد نظر ما از سن شخص دیگر بیشتر بود مقداری بزرگتر از صفر، اگر کمتر بود مقداری کمتر از صفر و اگر مساوی بود مقدار صفر برگشت داده می شود. کد زیر پیاده سازی رابط IComparable<T> توسط شی Person را نشان می دهد. برنامه جوانترین و پیرترین شخص را تشخیص می دهد.




public class Program
{
static void Main(string[] args)
{
Person person1 = new Person { FirstName = "John", LastName = "Smith", Age = 21 };
Person person2 = new Person { FirstName = "Mark", LastName = "Logan", Age = 19 };
Person person3 = new Person { FirstName = "Luke", LastName = "Adams", Age = 20 };

Person youngest = GetYoungest(person1, person2, person3);
Person oldest = GetOldest(person1, person2, person3);

Console.WriteLine("The youngest person is {0} {1}.",
youngest.FirstName, youngest.LastName);
Console.WriteLine("The oldest person is {0} {1}.",
oldest.FirstName, oldest.LastName);
Console.ReadKey();
}

private static Person GetYoungest(Person person1, Person person2, Person person3)
{
Person youngest = person1;

if (person2.CompareTo(youngest) == -1)
youngest = person2;

if (person3.CompareTo(youngest) == -1)
youngest = person3;

return youngest;
}

private static Person GetOldest(Person person1, Person person2, Person person3)
{
Person oldest = person1;

if (person2.CompareTo(oldest) == 1)
oldest = person2;

if (person3.CompareTo(oldest) == 1)
oldest = person3;

return oldest;
}
}


در خطوط 7-5 سه شی Person با مقادیر کاملا اختیاری ایجاد شده است. در خطوط 10-9 متغیرهایی برای نگهداری جوانترین و پیرترین شخص تعریف شده اند. در خط 9 متد GetYoungest() را فراخوانی کرده ایم. این متد در خطوط 19-30 تعریف شده است و سه شخص را که قرار است از لحاظ سنی با هم مقایسه شوند را قبول می کند.

در خط 21 فرض را بر این گذاشته ایم که اولین شخص (person1) جوانترین شخص است. سپس با استفاده از پیاده سازی متد CompareTo() تست می کنیم که آیا شخص دوم (person2) از شخص اول جوانتر است یا نه. در داخل متد مذکور سن شخص دوم و اول را با هم مقایسه می کنیم. اگر سن شخص دوم کمتر بود، باید مقدار 1- برگشت داده شده و در خط 24، person2 به عنوان جوانترین شخص معرفی شود. در خطوط 27-26 از تکنیکی مشابه برای شخص سوم استفاده کرده ایم. بعد از مقایسه جوانترین شخص در خط 29 به عنوان نتیجه برگشت داده می شود. در خط 10 متد GetOldest() که در خطوط 43-32 تعریف شده است فراخوانی می شود. کد های داخل این مت شبیه به متد GetYoungest() است با این تفاوت که تست می شود که آیا سن شخص دیگر بزرگتر از سن شخص مورد نظر ماست یا نه؟ بنابراین باید انتظار داشته باشیم که مقدار 1 به جای 1- توسط متد برگشت داده شود. در خطوط 15-12 نام جوانترین و پیرترین شخص چاپ می شود.



رابط <IComparer<T

IComparer<T> در یک کلاس جداگانه پیاده سازی می شود. هماطور که از نام این رابط پیداست، پیاده سازی آن باعث ایجاد یک کلاس مقایسه پذیر می شود. به وسیله این رابط می توان چندین مقایسه برای کلاس Person ایجاد کرد. مثلا در مثال کلاس Person، اشیاء ایجاد شده بر اساس سن(age)، نام و یا نام خانوادگی مورد مقایسه قرار می گیرند.




{
public int Compare(Person person1, Person person2)
{
return person1.FirstName.CompareTo(person2.FirstName);
}
}

public class LastNameComparer : IComparer
{
public int Compare(Person person1, Person person2)
{
return person1.LastName.CompareTo(person2.LastName);
}
}

public class AgeComparer : IComparer
{
public int Compare(Person person1, Person person2)
{
return person1.CompareTo(person2);
}
}


هنگام استفاده از این رابط لازم است یک متد به نام ()Compare که دو شیء قبول می کند و یک عدد صحیح را به عنوان نتیجه بر می گرداند را پیاده سازی کند. از آنجاییکه از رابط IComparer<Person> استفاده کرده ایم متد ()Compare به طور خودکار دو شئ Person قبول می کند. در مثال بالا با استفاده از کلاس FirstNameComparer که رابط IComparer را پیاده سازی می کند، دو شئ Person بر اساس نام مقایسه می شوند. در متد ()Compare به سادگی و با استفاده از متد از پیش تعریف شده ()CompareTo از کلاس String استفاده کرده ایم (چون خاصیت FirstName یک رشته است) و یک مقدار را به عنوان نتیجه بر می گردانیم.

به روشی مشابه از کلاس های LastNameComparer و AgeComparer برای مقایسه اشیاء برا اساس نا خانوادگی و سن استفاده می کنیم. متد Compare در صورتی که دو پارامتر با هم برابر باشند مقدار 0 ، اگر مپارامتر اول از پارامتر دوم بزگتر باشد مقداری بزرگتر از 0 و اگر پارمتر اول از پارامتر دوم کوچکتر باشد مقداری کوچکتر از 0 را بر می گرداند. در مثال زیر از کاربر سوال می شود که لیستی از اشیاء را قرار است بر اساس کدام خاصیت مرتب کند :




public class Program
{
static void Main(string[] args)
{
List persons = new List {
new Person { FirstName = "John", LastName = "Smith", Age = 21 },
new Person { FirstName = "Mark", LastName = "Logan", Age = 19 },
new Person { FirstName = "Luke", LastName = "Adams", Age = 20 }};

Console.WriteLine("Original Order");
foreach(Person p in persons)
Console.WriteLine("{0} {1}, Age: {2}", p.FirstName, p.LastName, p.Age);

Console.WriteLine("\nSort persons based on their:");
Console.WriteLine("[1] FirstName\n[2] LastName\n[3]Age");

Console.Write("Enter your choice: ");
int choice = Int32.Parse(Console.ReadLine());

ReorderPersons(choice, persons);

Console.WriteLine("New Order");
foreach (Person p in persons)
Console.WriteLine("{0} {1}, Age: {2}", p.FirstName, p.LastName, p.Age);
}

private static void ReorderPersons(int choice, List persons)
{
IComparer comparer;

if (choice == 1)
comparer = new FirstNameComparer();
else if (choice == 2)
comparer = new LastNameComparer();
else
comparer = new AgeComparer();

persons.Sort(comparer);
}
}


در خطوط 8-5 اشیا با مقادیر از پیش تعریف شده ای برای هر یک از خاصیت هایشان ایجاد شده است.در خطوط 12-11 ترتیب عادی و اصلی این اشیاء نمایش داده شده است. در خطوط 15-14 لیستی از انتخاب هایی که کاربر بر اساس آنها می تواند عملیات مرتب سازی را انجام دهد آورده شده است.در خطوط 18-17 از کاربر در مورد انتخابش سوال می شود. در خط 20 متد ()ReorderPersons متد از پیش تعریف شده ی خطوط 39-27 را فراخوانی می کنیم. این متد انتخاب کاربر و لیستی از اشیا که قرار است بر اساس خاصیتی که کاربر انتخاب کرده است مرتب شوند را قبول می کند. در داخل متد یک متغیر تعریف کرده ایم که از نوع IComparer<Person> است و در نتیجه می تواند هر نوع کلاسی که رابط مذکور را پیاده سازی می کند را شامل شود. در خطوط 36-31 چک می کنیم که اگر کاربر یک مقدار عددی خاص را انتخاب کرد، چه کارهایی انجام شود. در خط 38 از متد ()Sort کلاس List<T> استفاده کرده ایم. این متد دارای یک نسخه سربارگذاری شده است که یک شی IComparer<T> را قبول می کند. ما در خط 29 کلاس مقایسه کننده بر اساس نوع انتخاب کاربر را به این متد می دهیم و سپس متد ()Sort شی Person را بر اساس این کلاس مرتب می کند.

لینک مرجع : w3-farsi.com (http://www.w3-farsi.com/%D9%85%D9%82%D8%A7%DB%8C%D8%B3%D9%87-%D8%A7%D8%B4%DB%8C%D8%A7%D8%A1-%D8%A8%D8%A7-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-%D8%B1%D8%A7%D8%A8%D8%B7-%D9%87%D8%A7%DB%8C-icomparable/)