דילוג לתוכן
  • דף הבית
  • קטגוריות
  • פוסטים אחרונים
  • משתמשים
  • חיפוש
  • חוקי הפורום
כיווץ
תחומים

תחומים - פורום חרדי מקצועי

💡 רוצה לזכור קריאת שמע בזמן? לחץ כאן!
  1. דף הבית
  2. תכנות
  3. למה DoForEach לא קיים ב-LINQ?

למה DoForEach לא קיים ב-LINQ?

מתוזמן נעוץ נעול הועבר תכנות
24 פוסטים 4 כותבים 495 צפיות
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • קומפיונטק מנותק
    קומפיונטק מנותק
    קומפיונט
    כתב ב נערך לאחרונה על ידי
    #1

    שאלה שמנקרת בראשי הרבה זמן.

    המחלקה Enumerable ב-dotnet עשירה בעשרות פונקציות שמקילות על הפיתוח וחוסכות כתיבת קוד.
    אבל אני תוהה מדוע 'חסרה' שם פונקציה פשוטה? אפשר לקרוא לה לצורך הדוגמא DoForEach שתעבור על כל הרצף ותעשה פעולה זהה לכל אחד מהערכים.
    במקום לעבור על זה בלולאת foreach אפשר לקרוא לפונקציה פשוטה שתקבל את ה-action בארגומנט.

    אני לדוגמא בכל פרויקט מוסיף את ההרחבה הזאת:

    public static class EnumerableExtensions
    {
        public static void DoForEach<T>(this IEnumerable<T> source, Action<T> action)
        {
            foreach (var item in source)
            {
                action(item);
            }
        }
    }
    

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

    חגיח תגובה 1 תגובה אחרונה
    0
    • חגיח מחובר
      חגיח מחובר
      חגי
      השיב לקומפיונט ב נערך לאחרונה על ידי חגי
      #2

      @קומפיונט
      הרעיון הכללי של LINQ הוא ליצור pipeline של פונקציות שעובדות על קלט מסוים ומחזירות פלט מסוים, רעיון זהה לרעיון של תכנות פונקציונלי.
      בצורה הזאת מתאפשר "חישוב עצל", כלומר - עד שאתה לא צריך את הערך המסוים, הפונקציה הזו פשוט לא תרוץ, וכך אתה חוסך לך משאבים, גם של זיכרון וגם של עיבוד. ובצורה הזו הערך מחושב רק ברגע שצריך אותו, מה שהופך פעולות כמו take\skip להיות מאוד יעילות.
      ForEach מחייב אותך לבצע פעולה כאן ועכשיו, ולכן צריך גם לחשב את הערך הבא מהפונקציה, שזה נוגד את הרעיון של LINQ ושל ה"חישוב העצל".
      ישנה פונקציה ForEach שעובדת רק עם List, בהנחה והחלטת לזרוק את הרעיון של LINQ, והחלטת "לחשב" את כל הenumarable מיד, אתה יכול לעשות כזה דבר:

      myEnumerable.ToList().ForEach(...);
      

      כמובן שאתה יכול ליצור את הExtension method שלך, רק חשוב לדעת שזה מחשב את כל הערכים מייד.

      yossizY dovidD 2 תגובות תגובה אחרונה
      8
      • yossizY מנותק
        yossizY מנותק
        yossiz
        השיב לחגי ב נערך לאחרונה על ידי
        #3

        @חגי נהניתי התשובה, אני מתרשם שהתשובה שלך קרובה לאמת, אבל עדיין מדגדג לי תחושה שחסר לי משהו בהבנה...
        זה עדיין לא מרגיש לי תשובה ״בריסק״אית, מהסוג שאתה כבר לא מבין את השאלה

        אם למישהו יש מה להוסיף או להבהיר אשמח

        📧 יוסי@מייל.קום | 🌎 בלוג | ☕ קפה

        תגובה 1 תגובה אחרונה
        5
        • dovidD מנותק
          dovidD מנותק
          dovid ניהול
          השיב לחגי ב נערך לאחרונה על ידי
          #4

          @חגי תשובה יפה מאוד, אבל יש מתודות LINQ "חרוצות" המחייבות גישה מיידית לכל הערכים כמו הAggregate למיניהם, או הLast.
          אבל בכל אלו יש ייתרון ברור לקיצור: בשביל לבצע אותם צריך לולאה+משתנה חיצוני זמני.
          גם אני לעיתים מתחשק לי ForEach כמתודה במקום בלולאה, אבל אני לא מוצא לזה ייתרון שכלי, זה סה"כ נטיה רגשית לזרום יותר מידי עם תכנות פונקציונלי.

          אגב, הToList הוא בזבוז (בזבוז לגיטימי אבל צריך להיות מודע למחיר).

          מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

          בכל נושא אפשר ליצור קשר dovid@tchumim.com

          חגיח קומפיונטק 2 תגובות תגובה אחרונה
          5
          • חגיח מחובר
            חגיח מחובר
            חגי
            השיב לdovid ב נערך לאחרונה על ידי חגי
            #5

            @dovid
            אכן, ToList משכפל לך את Enumatable שלך.
            אתה בטוח שLast כן מחשב את כל הEnumerable?
            עשיתי בדיקה ו-Last לא מחשב הכל, ההיגיון מאחורי זה הוא שאתה לא צריך לחשב את שאר האלמנטים, אתה ישר מדלג (Skip) לסוף :smile:

            זאת הבדיקה:

            TestEnumerable t = new TestEnumerable();
            Console.WriteLine(t.Last().i);
            Console.WriteLine(t.Aggregate((i1, i2) => new Test(i1.i + i2.i)).i);
            class TestEnumerable : IEnumerable<Test>
            {
                private List<Test> _l = new List<Test>() { new Test(1), new Test(2),new Test(3),new Test(4),new Test(5) };
                public IEnumerator<Test> GetEnumerator()
                {
                    return _l.GetEnumerator();
                }
            
                IEnumerator IEnumerable.GetEnumerator()
                {
                    return _l.GetEnumerator();
                }
            }
            
            class Test
            {
                public Test(int i)
                {
                    _i = i;
                }
                public int i
                {
                    get
                    {
                        Console.WriteLine("got here {0}", _i);
                        return _i;
                    }
                    set { _i = value; }
                }
            
                private int _i;
            }
            

            וזאת התוצאה:

            got here 5
            5
            got here 1
            got here 2
            got here 3
            got here 3
            got here 6
            got here 4
            got here 10
            got here 5
            got here 15
            15
            
            dovidD 2 תגובות תגובה אחרונה
            1
            • dovidD מנותק
              dovidD מנותק
              dovid ניהול
              השיב לחגי ב נערך לאחרונה על ידי dovid
              #6

              @חגי הבדיקה שלך בודקת גישה למאפיין, לא גישה לאלמנט.
              IEnumerable חוסך גם גישה לאלמנט, למשל לקחת 200 שורות מהDB ולגשת לראשונה, בעצם לוקח רק את הראשונה. במקרה של Last הוא כמדומני עושה בדיקה, אם מדובר בIList הוא קופץ ישר לאחרון (עם גישת אינדקס ישירה) אבל אם לא (שאז הכי נחוץ החיסכון בגישה) הוא מוכרח לעבור בלולאה (MoveNext) עד לאחרון.

              מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

              בכל נושא אפשר ליצור קשר dovid@tchumim.com

              חגיח תגובה 1 תגובה אחרונה
              1
              • dovidD מנותק
                dovidD מנותק
                dovid ניהול
                השיב לחגי ב נערך לאחרונה על ידי dovid
                #7

                @חגי כתב בלמה DoForEach לא קיים ב-LINQ?:

                אכן, ToList משכפל לך את Enumatable שלך.

                זה גם משכפל, אבל זה גם מכריח אחזור מיידי של האוסף עוד לפני ביצוע הפעולה הראשונה.
                קח למשל כזה Enumerable:

                var listNumbers1to5 = new[] {1,2,3,4,5};
                var enumerableCollection = listNumbers1to5.Select(n => veryLongOperation(n));
                
                enumerableCollection.ToList().ForEach(c => Console.WriteLine("Process now element " + c))
                

                הConsole.WriteLine הראשון יקרה רק אחרי שכל האלמנטים יעברו את veryLongOperation. משא"כ בלולאת For Each.

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

                מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                בכל נושא אפשר ליצור קשר dovid@tchumim.com

                תגובה 1 תגובה אחרונה
                1
                • חגיח מחובר
                  חגיח מחובר
                  חגי
                  השיב לdovid ב נערך לאחרונה על ידי
                  #8

                  @dovid
                  ניסיתי לבדוק באמצעות Queue ו-List, וקראתי להם בצורה הזו:

                  TestQueue t = new TestQueue();
                  Console.WriteLine(t.Select(t =>
                  {
                      Console.WriteLine(t.i);
                      return t;
                  }).Last().i);
                  TestList t2 = new TestList();
                  Console.WriteLine(t2.Select(t =>
                  {
                      Console.WriteLine(t.i);
                      return t;
                  }).Last().i);
                  

                  בפועל זאת התוצאה:

                  got here 1
                  1
                  got here 2
                  2
                  got here 3
                  3
                  got here 4
                  4
                  got here 5
                  5
                  got here 5
                  5
                  got here 1
                  1
                  got here 2
                  2
                  got here 3
                  3
                  got here 4
                  4
                  got here 5
                  5
                  got here 5
                  5
                  

                  ההנחה שלי היתה שזאת בדיקה טובה בגלל שselect לא חייב לרוץ על שום אלמנט חוץ מהאחרון, ובqueue אי אפשר לגשת לפי אינדקס.
                  אז אני מניח שהבדיקה שלי היא הבעייתית, למה בList לא היתה טעינה עצלה רק של הערך האחרון?

                  dovidD תגובה 1 תגובה אחרונה
                  0
                  • קומפיונטק מנותק
                    קומפיונטק מנותק
                    קומפיונט
                    כתב ב נערך לאחרונה על ידי
                    #9

                    @חגי תודה על התשובות המקצועיות.

                    אני לא יודע אם Enumerable ו-LINQ קשורים בהכרח אחד לשני, אבל בכל מקרה יש הרבה הרחבות במחלקה Enumerable שלא מקיימות את התנאי הזה, קח לדוגמא את ()ToArray שזו נטו חיסכון בקוד. אז אם כן שאלתי עדין במקומה עומדת מדוע 'חסרה' פונקציה שתעשה איטרציה על כל הרצף?

                    זה שיש את זה ב-List זה מחזק את השאלה מדוע לא הוסיפו את זה גם ל-Enumerable כמו שלדוגמה ()ToArray מופיע בשניהם.

                    ודרך אגב, הרעיון המרכזי ב-LINQ הוא להפסיק לכתוב "איך" ולהתחיל לכתוב "מה", וגם לפי זה ההיגיון הפשוט הוא היה להוסיף פונקציית עזר כדוגמת ForEach.

                    תגובה 1 תגובה אחרונה
                    0
                    • קומפיונטק מנותק
                      קומפיונטק מנותק
                      קומפיונט
                      השיב לdovid ב נערך לאחרונה על ידי
                      #10

                      @dovid כתב בלמה DoForEach לא קיים ב-LINQ?:

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

                      אני מסכים עם דבריך, אבל לפי זה מדוע המפתחים טרחו לכתוב את ההרחבה ()ToList?! לכאורה גם לה אין שום יתרון שכלי. כי אפשר לקבל את אותה התוצאה באמצעות הכתיבה הזאת:

                      var list = new List<int>(enumerable)
                      
                      dovidD תגובה 1 תגובה אחרונה
                      0
                      • dovidD מנותק
                        dovidD מנותק
                        dovid ניהול
                        השיב לחגי ב נערך לאחרונה על ידי
                        #11

                        @חגי בשני המקרים, עצם הSelect הופך אותם חזרה לEnumerable חסר אינדקס.

                        מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                        בכל נושא אפשר ליצור קשר dovid@tchumim.com

                        חגיח תגובה 1 תגובה אחרונה
                        2
                        • dovidD מנותק
                          dovidD מנותק
                          dovid ניהול
                          השיב לקומפיונט ב נערך לאחרונה על ידי dovid
                          #12

                          @קומפיונט זה שעשו מתודה למרות שיש דרך נוספת לחיסכון של פעולה זו (שבבסיסה מחייבת לולאה פלוס משתנה) זה לא מחייב שיצרו פונקציה רק לחסוך לולאה נטו.
                          אני כעת חיפשתי בגוגל why linq not include ForEach ומצאתי תשובות עמוקות שקשורות לפילוספיה של LINQ, אתה מוזמן לקרוא אותם, אני לא כ"כ מתעמק.
                          בתכלס, אני חושב שאין בLINQ מתודת קיצור שחוסכת לולאה נטו.

                          מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                          בכל נושא אפשר ליצור קשר dovid@tchumim.com

                          קומפיונטק תגובה 1 תגובה אחרונה
                          2
                          • קומפיונטק מנותק
                            קומפיונטק מנותק
                            קומפיונט
                            השיב לdovid ב נערך לאחרונה על ידי
                            #13

                            @dovid אבל ב-<>List זה כן קיים, אז משמע שיש לזה יתרון כלשהו.

                            dovidD תגובה 1 תגובה אחרונה
                            1
                            • dovidD מנותק
                              dovidD מנותק
                              dovid ניהול
                              השיב לקומפיונט ב נערך לאחרונה על ידי dovid
                              #14

                              @קומפיונט מצאתי תשובה רשמית של אריק ליפרט:
                              https://docs.microsoft.com/en-us/archive/blogs/ericlippert/foreach-vs-foreach
                              הוא בעצם אומר:
                              א. יש לזה מעט מידי תועלת
                              ב. לכל מתודה (בפרט מיותרת) יש עלות ונזק
                              ג. זה נוגד את הפרנציפ של כל המתודות בLINQ שהם לא משפיעות כלום על כלום רק מחזירות ערך.

                              (מצאתי את זה דרך פוסט בסטאק: Executing a certain action for all elements in an Enumerable)

                              בקשר לFoEach של List, זה לא כ"כ קשה למה עשו את זה, זה נחמד ויפה, אך מצאתי גם דיון ביתרונות מעשיים: https://stackoverflow.com/q/225937/1271037
                              הכי התחברתי לטקסט הזה:

                              List.ForEach() says what you want done. foreach(item in list) also says exactly how you want it done. This leaves List.ForEach free to change the implementation of the how part in the future. For example, a hypothetical future version of .Net might always run List.ForEach in parallel, under the assumption that at this point everyone has a number of cpu cores that are generally sitting idle.

                              מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                              בכל נושא אפשר ליצור קשר dovid@tchumim.com

                              קומפיונטק תגובה 1 תגובה אחרונה
                              5
                              • קומפיונטק מנותק
                                קומפיונטק מנותק
                                קומפיונט
                                השיב לdovid ב נערך לאחרונה על ידי
                                #15

                                @dovid
                                אכן קראתי התשובה הוא מסביר שם נפלא למה ForEach אין מקומו ב-LINQ.
                                אבל עדיין יש כמה תמיהות כדלהלן:

                                בקשר לטענות הכותב:
                                א. למה דווקא ForEach מיותר וכי ה-ToList לא מיותר?! אדרבה, בעידן הנוכחי שהתכנות הפונקציונלי די פופולרי, קטע הקוד הבא יכול להיות מאוד אלגנטי:

                                Enumerable.Range(1, 20)
                                          .Select(n => n * 3)
                                          .Where(n => n % 2 == 0)
                                          .DoForEach(n => Console.WriteLine(n));
                                

                                הדרך המקבילה ב-foreach אמורה להיות קצת יותר מעצבנת... ובפרט כשהשרשור של האופרטורים יותר ארוך מהדוגמה.

                                ב. כנ"ל.

                                ג. זה באמת הנקודה שהכי דגדגה לי, כי היות והערך המוחזר מ-ForEach הוא void יוצא שהיא המתודה היחידה שלא מחזירה ערך כלשהו. אבל גם על זה אפשר להתפלסף, כי הרעיון של ForEach זהה לרעיון של ToList ו-ToArray אלא שספציפית הפעולה של ForEach לא אמורה להחזיר ערך כלשהו.
                                וחוץ מזה מדוע העיקרון הגורף של LINQ הוא להחזיר ערך כלשהו? למה לא להשתמש איתו כדי להשפיע על הרצף בלי להחזיר שום ערך? איזה דבר רע (או לא פילוסופי) יש בזה?!

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

                                dovidD תגובה 1 תגובה אחרונה
                                0
                                • dovidD מנותק
                                  dovidD מנותק
                                  dovid ניהול
                                  השיב לקומפיונט ב נערך לאחרונה על ידי dovid
                                  #16

                                  @קומפיונט
                                  א. ToList מצריך לולאה + משתנה. זה הרבה יותר משמעותי מלולאה נטו.
                                  ב. כנ"ל
                                  ג. הנקודה היא לא מה חוזר. קוראים לזה תכנות פונקציונלי.
                                  הפילוספיה היא שזה מתודות שאפשר להשתמש בהם בבטחה בלי לחשוש שהם ישפיעו על חלקים אחרים בתכנית שלך. לעולם לא יקרה שינוי לחלק בתכנית מפעולת LINQ שלא הושמה לתוך משתנה. בתוך המתודה ToList או ToArray קורה מה שקורה, אבל זה בסקופ סגור ובלתי משפיע, וזה יוצר פלט שאתה בוחר איך להשתמש בו.
                                  פונקציה שנכתבה לפי כללי התכנות הפונקציונלי בהכרח תחזיר ערך כי אחרת מה היא עושה, כי מה שקורה בגוף הפונקציה חייב להיות פרטי ובלתי נוגע לשום דבר אחר בעולם מלבד פלט.

                                  מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                                  בכל נושא אפשר ליצור קשר dovid@tchumim.com

                                  קומפיונטק תגובה 1 תגובה אחרונה
                                  4
                                  • קומפיונטק מנותק
                                    קומפיונטק מנותק
                                    קומפיונט
                                    השיב לdovid ב נערך לאחרונה על ידי
                                    #17

                                    @dovid כתב בלמה DoForEach לא קיים ב-LINQ?:

                                    א. ToList מצריך לולאה + משתנה. זה הרבה יותר משמעותי מלולאה נטו.

                                    למה ToList חוסך לולאה ומשתנה? זה לכאורה עושה return new List<TSource>(enum)

                                    ג. הנקודה היא לא מה חוזר. קוראים לזה תכנות פונקציונלי.

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

                                    אולי בגלל שלא מובן לי עד הסוף מה זה 'תכנות פונקציונלי' אז אני לא מצליח להבין מדוע חייב לחזור ערך. אין כזה דבר בתכנות פונקציונלי שחוזר ערך void?

                                    הפילוספיה היא שזה מתודות שאפשר להשתמש בהם בבטחה בלי לחשוש שהם ישפיעו על חלקים אחרים בתכנית שלך. לעולם לא יקרה שינוי לחלק בתכנית מפעולת LINQ שלא הושמה לתוך משתנה. בתוך המתודה ToList או ToArray קורה מה שקורה, אבל זה בסקופ סגור ובלתי משפיע, וזה יוצר פלט שאתה בוחר איך להשתמש בו.

                                    לכאורה המתודה ForEach שומרת על הכלל הזה, מכיוון שהיא לא תוכל לשנות ערכים כל שהם, (הייעוד שלה זה לעשות פעולה חיצונית עבור כל אחד מהערכים) היא אמנם תוכל לשנות מאפיינים בתוך ערכים, אבל זה גם בעיה שנמצאת ב-Select וב-Where אם כי זה לא הייעוד שלהם, אבל הם לא מספקים את ההגנה הזאת.

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

                                    תגובה 1 תגובה אחרונה
                                    2
                                    • חגיח מחובר
                                      חגיח מחובר
                                      חגי
                                      השיב לdovid ב נערך לאחרונה על ידי
                                      #18

                                      @dovid
                                      בכולל אחה"צ באמצע תוס' קשה פתאום עלה לי הרעיון שבשביל לבדוק את זה, אפשר לממש את הIEnumerator לבד.

                                      dovidD תגובה 1 תגובה אחרונה
                                      0
                                      • dovidD מנותק
                                        dovidD מנותק
                                        dovid ניהול
                                        השיב לחגי ב נערך לאחרונה על ידי dovid
                                        #19

                                        @חגי נכון.

                                        void Main()
                                        {
                                            var test = new testList();
                                            Console.WriteLine("ILIST ACCESS:");
                                            Console.WriteLine(test.Last());
                                        
                                            var test2 = test.Select(t => t * 2);
                                            Console.WriteLine("IENUMERABLE ACCESS:");
                                            Console.WriteLine(test2.Last());
                                        }
                                        
                                        
                                        public class ProxyIEnumerator :IEnumerator<int>
                                        {
                                            IEnumerator<int> targetEnum;
                                            public ProxyIEnumerator(IList<int> _source) => targetEnum = _source.GetEnumerator();
                                        
                                            public bool MoveNext()
                                            {
                                                Console.WriteLine("MoveNext call");
                                                return targetEnum.MoveNext();
                                            }
                                        
                                            public void Reset() => targetEnum.Reset();
                                            public int Current => targetEnum.Current;
                                        
                                            object IEnumerator.Current => targetEnum.Current;
                                            public void Dispose() => targetEnum.Dispose();
                                        
                                        }
                                        
                                        
                                        
                                        class testList : IList<int>
                                        {
                                            private int[] source = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
                                        
                                            public int Count => source.Length;
                                        
                                            public int this[int index]
                                            {
                                                get
                                                {
                                                    Console.WriteLine("access " + index);
                                                    return source[index];
                                                }
                                                set => throw new NotImplementedException();
                                            }
                                        
                                            public IEnumerator<int> GetEnumerator() => new ProxyIEnumerator(source);
                                        
                                        
                                            public bool IsReadOnly => throw new NotImplementedException();
                                            IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
                                            public void Add(int item) => throw new NotImplementedException();
                                            public void Clear() => throw new NotImplementedException();
                                            public bool Contains(int item) => throw new NotImplementedException();
                                            public void CopyTo(int[] array, int arrayIndex) => throw new NotImplementedException();
                                            public int IndexOf(int item) => throw new NotImplementedException();
                                            public void Insert(int index, int item) => throw new NotImplementedException();
                                            public bool Remove(int item) => throw new NotImplementedException();
                                            public void RemoveAt(int index) => throw new NotImplementedException();
                                        }
                                        

                                        פלט:

                                        ILIST ACCESS:
                                        access 8
                                        9
                                        IENUMERABLE ACCESS:
                                        MoveNext call
                                        MoveNext call
                                        MoveNext call
                                        MoveNext call
                                        MoveNext call
                                        MoveNext call
                                        MoveNext call
                                        MoveNext call
                                        MoveNext call
                                        MoveNext call
                                        18
                                        

                                        מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                                        בכל נושא אפשר ליצור קשר dovid@tchumim.com

                                        תגובה 1 תגובה אחרונה
                                        3
                                        • קומפיונטק מנותק
                                          קומפיונטק מנותק
                                          קומפיונט
                                          כתב ב נערך לאחרונה על ידי קומפיונט
                                          #20

                                          @חגי + @dovid

                                          אם אני מבין נכון אז הדוגמא ש @dovid הביא ממחישה שכשקוראים ל-Last אז אם האובייקט של הרצף ממש את IList`1 אז ישר מתבצע קפיצה לאינדקס האחרון, ואם לא אז ה-Last עובר ו'מעיר' את כל הרצף עד שחוזר false מה-()MoveNext.
                                          אם הבנתי נכון אז אפשר לראות את זה ב-ILSpy:

                                          אגב, בדקתי, ToList לא משכפל את הרצף, הוא רק יוצר Reference חדש לערכים הקיימים.
                                          עריכה: אפילו המתודה CopyTo ב-List`1 משכפלת רק את ה-Reference.

                                          LastIlSpy.jpg

                                          dovidD תגובה 1 תגובה אחרונה
                                          0

                                          • 1
                                          • 2
                                          בא תתחבר לדף היומי!
                                          • התחברות

                                          • אין לך חשבון עדיין? הרשמה

                                          • התחברו או הירשמו כדי לחפש.
                                          • פוסט ראשון
                                            פוסט אחרון
                                          0
                                          • דף הבית
                                          • קטגוריות
                                          • פוסטים אחרונים
                                          • משתמשים
                                          • חיפוש
                                          • חוקי הפורום