שאלה|IEnumerable - תכנות - HWzone פורומים
עבור לתוכן
  • צור חשבון

שאלה|IEnumerable


maimon_y

Recommended Posts

#C

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

IEnumerable זה אינטרפייס שכולל בתוכו מתודה אחת Get Enumerator שכוללת את move next current ,reset .

() IEnumerator IEnumerable.GetEnumerator

}

;() return GetEnumerator

{

שאלות:

1)למה המימוש של Get Enumerator מתבצע ככה?

2)הקטע שמודגש באדום זה הטיפוס שהמתודה מחזירה?

3)למה הוא מחזיר GetEnumerator?

4)בנוסף אני ראיתי כמה דרכים שונות לממש את IEnumerable

בקיצור אם מישהו יכול לתת הסבר קצר על כל חלק בנושא הזה אני יודה לו מאוד.

קישור לתוכן
שתף באתרים אחרים

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

המטרה של IEnumerable היא לאפשר להתייחס לאובייקט שלך בתור סדרה של איברים, ולעבור עליהם באמצעות foreach. פה יש דוגמה איך היה נהוג להשתמש ב-IEnumerable (עוד מעט אני אסביר למה זה כבר לא נהוג). כפי שאתה רואה בדוגמה, מה שעושים הוא להגדיר מחלקה שמממשת את הממשק IEnumerator (והיא זו שמממשת את הפונקציה reset וכו'). הפונקציה GetEnumerator פשוט צריכה להחזיר מופע של המחלקה הזו - במקרה הזה return new PeopleEnum.

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

foreach (Person p in people) { ... }

הבעיה היא שהקומפיילר גם יתן לך לכתוב את זה:

foreach (String p in people) { ... }

הקוד יתקמפל, אבל יעוף בזמן ריצה, כי אי אפשר להמיר אובייקט מטיפוס Person ל-String.

לשם כך הציגו בדוטנט 2 את ה-generics. ג'נריקס מאפשרים לך להגדיר מחלקה שמתייחסת לטיפוס ספציפי. לדוגמה, <IEnumerable<int אומר שהמחלקה שלך לא סתם מייצגת סדרה של אובייקטים, היא מייצגת סדרה של intים. בדוגמה הנ"ל, אם האובייקט People היה מממש את <IEnumerable<Person במקום סתם IEnumerable, אז הקוד הזה לא יתקמפל:

foreach (String p in people) { ... }

כי הוא ידע כבר בזמן הקומפילציה שהאיברים של people הם לא סתם אובייקטים, אלא אובייקטים מטיפוס Person.

באופן הבסיסי ביותר, <IEnumerable<T הוא כמו IEnumerable אבל במקום ש-GetEnumerator מחזירה IEnumerator, היא מחזירה <IEnumerator<T.

<IEnumerator<T היא כמו IEnumerator, רק שהתכונה Current היא מטיפוס T ולא סתם Object.

הבעיה היא שמיקרוסופט החליטו ש-<IEnumerator<T יורשת מ-IEnumerable, ולכן יש לה שתי תכונות בשם Current - אחת שהיא ישרה מ-IEnumerable ומחזירה Object, ואחת חדשה שמחזירה T. לכן כשאתה מממש <IEnumerator<T צריך לדאוג לממש את שתי התכונות האלה כמו בדוגמה שכאן (ראה בסוף את המימוש של Current).

באותו אופן, <IEnumerable<T יורשת מ-IEnumerable, ולכן יש לה שתי פונקציות GetEnumerator - אחת שמחזירה IEnumerator ואחת שמחזירה <IEnumerator<T. לכן כשאתה מממש <IEnumerable<T אתה צריך לממש את GetEnumerator שמחזירה <IEnumerator<T כמו בדוגמה הקודמת (ע"י יצירת מופע חדש של האנומרטור), וגם את IEnumerable.GetEnumerator שפשוט קוראת ל-GetEnumerator האחרת וזהו. בגלל זה יש את הכפילות המוזרה הזו.

חוץ מזה, הוסיפו גם מילה חדשה בשם yield. המילה הזו היא מילה שמאפשרת לך לממש אנומרטורים ו-IEnumerable בצורה הכי קלה, בלי להגדיר שום מחלקות נוספות.

https://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx

לדעתי זו הדרך הכי כדאית ליצור אנומרטור, כי היא ממש ממש קלה ולא צריך להסתבך עם כלום.

קישור לתוכן
שתף באתרים אחרים

  • 2 שבועות מאוחר יותר...

באופן הבסיסי ביותר, <IEnumerable<T הוא כמו IEnumerable אבל במקום ש-GetEnumerator מחזירה IEnumerator, היא מחזירה <IEnumerator<T.

<IEnumerator<T היא כמו IEnumerator, רק שהתכונה Current היא מטיפוס T ולא סתם Object.

הבעיה היא שמיקרוסופט החליטו ש-<IEnumerator<T יורשת מ-IEnumerable, ולכן יש לה שתי תכונות בשם Current - אחת שהיא ישרה מ-IEnumerable ומחזירה Object, ואחת חדשה שמחזירה T. לכן כשאתה מממש <IEnumerator<T צריך לדאוג לממש את שתי התכונות האלה כמו בדוגמה שכאן (ראה בסוף את המימוש של Current).

באותו אופן, <IEnumerable<T יורשת מ-IEnumerable, ולכן יש לה שתי פונקציות GetEnumerator - אחת שמחזירה IEnumerator ואחת שמחזירה <IEnumerator<T. לכן כשאתה מממש <IEnumerable<T אתה צריך לממש את GetEnumerator שמחזירה <IEnumerator<T כמו בדוגמה הקודמת (ע"י יצירת מופע חדש של האנומרטור), וגם את IEnumerable.GetEnumerator שפשוט קוראת ל-GetEnumerator האחרת וזהו. בגלל זה יש את הכפילות המוזרה הזו.

חוץ מזה, הוסיפו גם מילה חדשה בשם yield. המילה הזו היא מילה שמאפשרת לך לממש אנומרטורים ו-IEnumerable בצורה הכי קלה, בלי להגדיר שום מחלקות נוספות.

https://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx

לדעתי זו הדרך הכי כדאית ליצור אנומרטור, כי היא ממש ממש קלה ולא צריך להסתבך עם כלום.

קישור לתוכן
שתף באתרים אחרים

האם הפונקציה מחזירה רק מחלקות שיורשות IEnumerator ?

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

ובמה הפיסקה הזאת שונה מהפיסקה שנמצאת בתגובה הפתחיה?

מה? לא הבנתי את השאלה.

קישור לתוכן
שתף באתרים אחרים

כשאתה מממש ממשק, אתה יכול לממש את הפונקציות באופן הרגיל שאתה מכיר, או בצורה explicit. במימוש explicit אתה מוסיף את שם הממשק שאתה מממש לפני שם הפונקציה.

הנה דף שמסביר את זה כולל דוגמאות.

זה נחוץ כשאתה מממש שני ממשקים שיש להם פונקציה או תכונה עם אותו שם.

ב-<IEnumerable<T אתה צריך לממש פעמיים את הפונקציה GetEnumerator - פעם אחת עבור <IEnumerable<T ופעם אחת עבור IEnumerable. בגלל שיש להן אותו שם, צריך לממש אחת מהן באופן expilcit.

קישור לתוכן
שתף באתרים אחרים

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

×
  • צור חדש...