111. IEqualityComparer

הכרנו בעבר את Equals בשבוע השווה (טיפים 76-80),

לפעמים יש לנו מחלקה שכבר ממומש לה Equals, אבל אנחנו מעוניינים להשוות איברים בצורה אחרת.

לדוגמה, נניח שאנחנו עובדים עם מחרוזות. השוואה של מחרוזות היא Case-sensitive, אבל לפעמים אנחנו מעוניינים להשוות מחרוזות לא Case-Sensitive.

או דוגמה אחרת, כאשר אנחנו משווים שני מספרים, אנחנו מתייחסים אל הסימן שלהם. אולי נרצה לפעמים להשוות מספרים בלי להתייחס לסימן שלהם.

בשביל כל הבעיות האלה, הומצא ממשק ששמו הוא IEqualityComparer.

לממשק יש שתי פונקציות. אחת משווה בין שני אובייקטים, והשנייה מחזירה HashCode של אובייקט נתון.

כך אנחנו יכולים לדרוס את ההתנהגות ואת הצורה בה אנחנו מגדירים מתי שוויון מתקיים.

קיימת, כמובן, גרסה גנרית וגרסה לא גנרית. הגרסה הלא גנרית קיימת בעיקר מסיבות היסטוריות ומשווה שני objectים. הגרסה הגנרית היא מה שיותר מעניין אותנו.

לדוגמה, נניח ואנחנו מעוניינים להשוות שתי מחרוזות בשיטה החדשה, נצטרך לממש משהו כזה:

1
2
3
4
5
6
7
8
9
10
11
12
public class StringIgnoreCaseSensitiveComparer : IEqualityComparer<string>
{
public bool Equals(string x, string y)
{
return string.Equals(x, y, StringComparison.InvariantCultureIgnoreCase);
}
public int GetHashCode(string obj)
{
return obj.ToUpper().GetHashCode();
}
}

ואז נוכל להשוות שתי מחרוזות כך:

1
2
3
4
5
6
StringIgnoreCaseSensitiveComparer stringComparer = new StringIgnoreCaseSensitiveComparer();
if (stringComparer.Equals("Hello World", "HELLO WORLD"))
{
// True
}

מה היתרון? כרגע לא נראה שיש בדיוק יתרון בעבודה כזו, אך נראה בהמשך שעבודה כזאת עשויה לפשט לנו תהליכים, מאחר והרבה מקומות בFramework יודעים לעבוד עם IEqualityComparer.

במטרה לחסוך לנו זמן, יש מספר מחלקות שאנחנו יכולים להשתמש בהם בבואנו לכתוב IEqualityComparer משלנו. אחת מהן היא EqualityComparer<T>, בה אנחנו רק צריכים לממש את Equals וGetHashCode בדרך שאנחנו רוצים להשוות איברים. ההבדל בין ירושה ממחלקה זו, למימוש IEqualityComparer<T> הוא EqualityComparer<T> מממש גם את הגרסה הלא גנרית של IEqualityComparer.

בנוסף, יש את המימוש הדיפולטי של EqualityComparer<T>, שראינו אותו בעבר (טיפ מספר 79):

1
2
3
4
5
6
IEqualityComparer<string> stringComparer = EqualityComparer<string>.Default;
if (stringComparer.Equals("Hello World", "HELLO WORLD"))
{
// False
}

הוא פשוט משווה שתי מחרוזות באמצעות הEquals וGetHashCode הדיפולטיים של הטיפוס.

אנחנו עוד נראה שימושים של IEqualityComparer<T>.

שבוע שווה

שתף