פעם קודמת ראינו איך ממומש foreach.
נזכיר, foreach, לדוגמה כזה:
|
|
זה בעצם syntactic sugar ל
|
|
הבעיה – כפי שאנחנו רואים יכול להיות לנו IEnumerator שמכיל Type אחד, והforeach יעבוד לנו גם כשנרוץ עליו עם Type אחר.
למשל, הקוד הבא יתקמפל:
|
|
ונחטוף Exception על הסבה לא נכונה בזמן ריצה.
בC# 2.0, כידוע, נוספו Generics לשפה והיינו מצפים שהם ידעו לדאוג לכך שהקוד לא יתקמפל.
אם באמת נעשה משהו כזה:
|
|
זה אכן לא יתקמפל.
Cannot convert type ‘Person’ to ‘Fruit’
האם Generics הצילו אותנו?
לא לגמרי
הסבות הן מהשטן,
אם יהיה לנו משהו כזה:
|
|
וכעת נעשה משהו כזה:
|
|
הקוד שוב יתקמפל!
הסיבה היא שאמנם Fruit אינו מממש IPerson, אבל אולי יש מישהו שיורש מFruit שכן מממש IPerson?
נוכל לפתור את הבעיה האחרונה אם המחלקה שלנו היא sealed:
|
|
במקרה כזה:
|
|
לא מתקמפל. אנחנו מקבלים את השגיאה הבאה בזמן קימפול:
Cannot convert type ‘IPerson’ to ‘Fruit’
מאחר וFruit אינו מממש IPerson, והוא sealed, לא ייתכן שיש מישהו שיורש מFruit שכן מממש IPerson.
מסקנות שכדאי לקחת מכאן:
- כאשר אתם עובדים עם דברים שמממשים סתם IEnumerable, צריך מאוד להיזהר על הType שעושים איתו foreach. הנושא כאוב מאוד לגבי Collectionים מFramework 1.0 שלא הועברו לממשק הגנרי, ביניהם הCollectionים שבאו מSystem.Data (ביניהם DataTable וכל החברים), והCollectionים שבאו מSystem.Windows.Forms.
- כאשר אתם עובדים עם IEnumerable של ממשק, גם עליכם להיזהר!
- תשתדלו להפוך מחלקות לsealed אם אתם לא רוצים שירשו מהן.
המשך יום בר מנייה טוב