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

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

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

נתקלתי אתמול בבאג חמוד

מתוזמן נעוץ נעול הועבר תכנות
10 פוסטים 5 כותבים 402 צפיות 8 עוקבים
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
תגובה
  • תגובה כנושא
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • M מנותק
    M מנותק
    Mordechai 0
    כתב נערך לאחרונה על ידי
    #1

    @dovid וכל שאר המומחים לא לגלות😉

    אתמול נתקלתי בבאג חמוד שב"ה אחרי חצי שעה הצלחתי לפתור, והחלטתי לשתף
    כדי לפשט ולהראות את הבאג, הנה דוגמה קצרה:

    var list = new List<Action>();
    for (int i = 0; i < 3; i++)
    {
        list.Add(() => Console.WriteLine(i));
    }
    list.ForEach(x => x());
    

    ציפיתי שהפלט יהיה:
    0
    1
    2

    אבל במקום זה, קיבלתי:
    3
    3
    3

    חגיח תגובה 1 תגובה אחרונה
    4
    • M Mordechai 0

      @dovid וכל שאר המומחים לא לגלות😉

      אתמול נתקלתי בבאג חמוד שב"ה אחרי חצי שעה הצלחתי לפתור, והחלטתי לשתף
      כדי לפשט ולהראות את הבאג, הנה דוגמה קצרה:

      var list = new List<Action>();
      for (int i = 0; i < 3; i++)
      {
          list.Add(() => Console.WriteLine(i));
      }
      list.ForEach(x => x());
      

      ציפיתי שהפלט יהיה:
      0
      1
      2

      אבל במקום זה, קיבלתי:
      3
      3
      3

      חגיח מנותק
      חגיח מנותק
      חגי
      כתב נערך לאחרונה על ידי
      #2

      @Mordechai-0 כתב בנתקלתי אתמול בבאג חמוד:

      @dovid וכל שאר המומחים לא לגלות

      למי כן מותר לגלות?

      M תגובה 1 תגובה אחרונה
      2
      • חגיח חגי

        @Mordechai-0 כתב בנתקלתי אתמול בבאג חמוד:

        @dovid וכל שאר המומחים לא לגלות

        למי כן מותר לגלות?

        M מנותק
        M מנותק
        Mordechai 0
        כתב נערך לאחרונה על ידי
        #3

        @חגי כתב בנתקלתי אתמול בבאג חמוד:

        למי כן מותר לגלות?

        😁

        לכל מי שהשקיע מחשבה בשביל הפיתרון

        תגובה 1 תגובה אחרונה
        2
        • א מנותק
          א מנותק
          אבי
          כתב נערך לאחרונה על ידי אבי
          #4

          אגב אם תשתמש ב foreach

          var list = new List<Action>();
          foreach (var i in Enumerable.Range(0, 3))
          {
              list.Add(() => Console.WriteLine(i));
          }
          list.ForEach(x => x());
          

          התוצאה כן תהיה
          0
          1
          2

          for - הלמבדה לוכדת את אותו משתנה ולא את הערך ברגע היצירה, ולכן תקבל תמיד את הערך האחרון (3).
          foreach - כל איטרציה מקבלת משתנה חדש.

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

            @אבי יש לציין גם שזה רק מC# 5... זה היה אחד הBreaking Change הבודדים שהיו באבולוציה של C# (אבל ההתנהגות הקודמת נחשבה לבאג).

            • מנטור אישי בתכנות והמסתעף – להתקדם לשלב הבא!
            • בכל נושא אפשר ליצור קשר dovid@tchumim.com
            תגובה 1 תגובה אחרונה
            3
            • קומפיונטק מנותק
              קומפיונטק מנותק
              קומפיונט
              כתב נערך לאחרונה על ידי
              #6

              בחזרה לנושא המקורי
              משהו יכול להסביר מה זה שונה מ foreach או מ:

              for (int i = 0; i < 3; i++)
              {
                  var j = i;
                  list.Add(() => Console.WriteLine(j));
              }
              

              שזה מפיק: [2 ,1 ,0]

              הרי גם i וגם j הם לוקאליים, אז למה הלמדה משתמשת פעם אחת בערך ופעם אחת ברפרנס?

              חגיח תגובה 1 תגובה אחרונה
              1
              • קומפיונטק קומפיונט

                בחזרה לנושא המקורי
                משהו יכול להסביר מה זה שונה מ foreach או מ:

                for (int i = 0; i < 3; i++)
                {
                    var j = i;
                    list.Add(() => Console.WriteLine(j));
                }
                

                שזה מפיק: [2 ,1 ,0]

                הרי גם i וגם j הם לוקאליים, אז למה הלמדה משתמשת פעם אחת בערך ופעם אחת ברפרנס?

                חגיח מנותק
                חגיח מנותק
                חגי
                כתב נערך לאחרונה על ידי חגי
                #7

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

                קומפיונטק תגובה 1 תגובה אחרונה
                3
                • dovidD dovid פיצל נושא זה
                • חגיח חגי

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

                  קומפיונטק מנותק
                  קומפיונטק מנותק
                  קומפיונט
                  כתב נערך לאחרונה על ידי
                  #8

                  @חגי אתה מתכוונן שלמשתנה i יש סקופ יותר ארוך מ - j, אבל בפועל שניהם משתנים לוקאליים.

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

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

                  אפשר לאמת את זה על ידי בדיקת כתובות האובייקטים ברשימה.

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

                    @קומפיונט "לוקלי" זה בדיוק אורך הסקופ (לא מכיר משמעות אחרת למילה לוקלי בC#).
                    בכל איטרציה נוצר משתנה חדש j. פונקציית הלמבדה שנוצרת בכל איטרציה לוכדת את הרפרנס למשתנה שונה בכל פעם (שלכולם קוראים j אבל הם מקומות נפרדים בזיכרון).
                    בכל מקרה לכידה של משתנים בסקופ היא תמיד רפרנס למשתנה ואף פעם לא העתקת ערך - שינוי של הערך במשתנה ישפיע תמיד על הפונקציה הלוכדת (וגם לכן זה מעכב את איסופם באספן הזבל כל עוד יש מצביע חי לפונקציה).

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

                    • מנטור אישי בתכנות והמסתעף – להתקדם לשלב הבא!
                    • בכל נושא אפשר ליצור קשר dovid@tchumim.com
                    קומפיונטק תגובה 1 תגובה אחרונה
                    3
                    • dovidD dovid

                      @קומפיונט "לוקלי" זה בדיוק אורך הסקופ (לא מכיר משמעות אחרת למילה לוקלי בC#).
                      בכל איטרציה נוצר משתנה חדש j. פונקציית הלמבדה שנוצרת בכל איטרציה לוכדת את הרפרנס למשתנה שונה בכל פעם (שלכולם קוראים j אבל הם מקומות נפרדים בזיכרון).
                      בכל מקרה לכידה של משתנים בסקופ היא תמיד רפרנס למשתנה ואף פעם לא העתקת ערך - שינוי של הערך במשתנה ישפיע תמיד על הפונקציה הלוכדת (וגם לכן זה מעכב את איסופם באספן הזבל כל עוד יש מצביע חי לפונקציה).

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

                      קומפיונטק מנותק
                      קומפיונטק מנותק
                      קומפיונט
                      כתב נערך לאחרונה על ידי קומפיונט
                      #10

                      אני משאיר את זה פה למי שבכל זאת אוהב לראות איך זה קורא בפועל.

                      @dovid כתב בנתקלתי אתמול בבאג חמוד:

                      חוטא לשפת C#

                      ובלבד שיכוון ליבו

                      תגובה 1 תגובה אחרונה
                      1
                      תגובה
                      • תגובה כנושא
                      התחברו כדי לפרסם תגובה
                      • מהישן לחדש
                      • מהחדש לישן
                      • הכי הרבה הצבעות


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

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

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