142. The difference between IsSubclassOf and IsAssignableFrom

לפעמים אנחנו מעוניינים לדעת האם Type מסוים הוא תת-טיפוס של Type נתון (כלומר, יורש מהType נתון, או מממש את הType נתון).

לכאורה נראה שיש פתרון פשוט לזה, באמצעות הפונקציה IsSubclassOf. אלא שפונקציה זו עושה בעיות במקרים הבאים:

  • אם הטיפוסים שווים, היא תחזיר false.

לדוגמה:

1
2
3
4
if (typeof(Shape).IsSubclassOf(typeof(Shape)))
{
// False
}
  • אם הטיפוס שאנחנו רוצים לבדוק, האם הטיפוס השני יורש ממנו, הוא ממשק, נקבל false.

לדוגמה, אם יש לנו מחלקה כזאת:

1
public class Shape : IDrawable

לא נכנס לתנאי (באופן אולי מפתיע)

1
2
3
4
if (typeof(Shape).IsSubclassOf(typeof(IDrawable)))
{
// False
}
  • בשאר המקרים (מחלקה שיורשת ממחלקה), הדבר הזה כן יעבוד:
1
2
3
4
if (typeof(Circle).IsSubclassOf(typeof(Shape)))
{
// True
}

כדי שבכל זאת נוכל לבדוק האם טיפוס יורש (במובן הC#י החלש - כלומר מממש/יורש/שווה) מטיפוס אחר, קיימת פונקציה אחרת בשם IsAssignableFrom. פונקציה זו היא פונקציה של Type המקבלת Type שני, ובודקת האם הType השני "יורש" (במובן הC#י החלש) מהType הראשון, או במילים אחרות, האם אפשר להסב (בהסבה סטנדרטית) את הטיפוס השני לטיפוס הראשון. לדוגמא:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if (typeof(Shape).IsAssignableFrom(typeof(Shape)))
{
// True
}
if (typeof(IDrawable).IsAssignableFrom(typeof(Shape)))
{
// True
}
if (typeof(Shape).IsAssignableFrom(typeof(Circle)))
{
// True
}

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

typeof(Shape).IsAssignableFrom(typeof(Circle)) לעומת typeof(Circle).IsSubclassOf(typeof(Shape)).

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

שתף