79. Equatable.DefaultComparer

בהמשך לטיפ היומי של אתמול,

ראינו איך אפשר להשוות שני משתנים בEquals בלי לבדוק אם אחד מהם הוא null.

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

מסתבר שקיימת דרך דומה לבצע את ההשוואה בצורה הבאה:

במקום לכתוב ככה:

1
2
3
4
if (object.Equals(a, b))
{
// ...
}

נוכל לכתוב ככה:

1
2
3
4
if (EqualityComparer<int>.Default.Equals(a, b))
{
// ...
}

כאשר לEquals נוכל להעביר רק טיפוסים מהסוג הגנרי.

מה הרווחנו:

  1. Typed safety – אם ברצוננו להשוות רק משתנים מאותו טיפוס, זה יבדוק את זה.
  2. מניעה מboxing – בקריאה למתודה אין boxing
  3. התחשבות בIEquatable<T> - אם הטיפוסים שאנחנו משווים מממשים IEquatable<T>, המתודה הזאת תשתמש בEquals של הממשק במקום בEquals שלobject, ולכן נמנע מboxing במידה והממשק מממומש.
  4. ביצועים – מאחר וחסכנו boxing, הביצועים יהיו טובים יותר.

אני רוצה להוסיף ולציין מקרה שבו נרצה להשתמש במתודות Equals הסטטיות:

כשאנחנו נמצאים במתודה עם טיפוסים גנריים ואנחנו רוצים להשוות אותם, לא ניתן להשתמש ב== עבור המשתנים הגנריים, מאחר והקומפיילר לא יכול לגלות בזמן קימפול האם האופרטור == קיים לטיפוס:

1
2
3
4
5
6
7
public static void MyMethod<T>(T first, T second)
{
if (first == second)
{
// Compile error.
}
}

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

  1. להשתמש בהשוואת referenceים
  2. להשתמש בEquals

נוכל לכתוב כך:

1
2
3
4
5
6
7
public static void MyMethod<T>(T first, T second)
{
if (object.Equals(first, second))
{
// ...
}
}

או יותר טוב, כך:

1
2
3
4
5
6
7
public static void MyMethod<T>(T first, T second)
{
if (EqualityComparer<T>.Default.Equals(first, second))
{
// ...
}
}

המשך יום שווה טוב

שתף