Type firstGenericType = provideSomethingGeneric.ReturnType;
Type secondGenericType = provideAnotherGenericThing.ReturnType;
למרבה ההפתעה אם נקרא לקוד הבא לא נכנס לתנאי:
1
2
3
4
if (firstGenericType.Equals(secondGenericType))
{
// False
}
לפני שאתם מחליטים לפרוש מC# ומעולם התוכנה, ננסה להסביר למה זה קורה.
הסיבה היא שהארכיטקטים של מיקרוסופט החליטו ששני הטיפוסים האלה המייצגים את GenericClass, הם לא שווים.
למה? הסיבה היא כי הם נוצרים ע"י פרמטרים גנריים שונים: הראשון מתקבל ע"י שליחת פרמטר גנרי לפונקציה ProvideSomethingGeneric, ואילו השני מתקבל ע"י שליחת פרמטר גנרי לפונקציה ProvideAnotherGenericThing. אבל אלה שני פרמטרים גנריים שונים!
בפרט, אם ננסה להשוואות מתודות של הטיפוסים, גם לא נקבל שוויון:
if (firstGenericTypeMethod.Equals(secondGenericTypeMethod))
{
// False
}
הדבר הזה יכול להפריע לנו להשוות מתודות.
למשל, במקרה ואנחנו רוצים לאסוף מתוך אוסף של טיפוסים את כל המתודות שמקיימות תנאי מסוים, וכל אחת רק פעם יחידה, אנחנו עשויים ליפול בהשוואה של המתודות, כשאנחנו בודקים איזה מתודות כבר אספנו.
איך אפשר לפתור את זה?
בעצם מעניין אותנו אם לשתי המתודות יש אותה החתימה.
הברקה מסוימת (שהיא גם Patch) היא שהToString של MethodInfo מחזיר משהו… שדומה לחתימה של המתודה!
לכן אפשר לנצל עובדה זו. ניצור IEqualityComparer שמשווה אובייקטים לפי הToStringים שלהם:
1
2
3
4
5
6
7
8
9
10
11
12
public class ToStringComparer<T> : IEqualityComparer<T>
{
publicboolEquals(T x, T y)
{
return x.ToString() == y.ToString();
}
publicintGetHashCode(T obj)
{
returnobj.ToString().GetHashCode();
}
}
כעת נוכל להשוואות מתודות וטיפוסים כך:
1
2
3
4
5
6
7
8
9
10
11
12
13
IEqualityComparer<MethodInfo> methodComparer = new ToStringComparer<MethodInfo>();
if (methodComparer.Equals(firstGenericTypeMethod, secondGenericTypeMethod))
{
// True
}
IEqualityComparer<Type> typeComparer = new ToStringComparer<Type>();
if (typeComparer.Equals(firstGenericType, secondGenericType))
{
// True
}
הדבר יכול מאוד לעזור לנו בכל המקומות בFramework המקבלים IEqualityComparer. (ראו גם טיפים מספר 111-116)