DCSIMG
כשכותבים switch, האם זה נשאר כך ? - שלמה גולדברג (הרב דוטנט)

שלמה גולדברג (הרב דוטנט)

מרצה בסלע ויועץ בעולם ה - net.

כשכותבים switch, האם זה נשאר כך ?

טוב, כנראה החוויה הקשה שעברתי עם מחיקת הפוסט של ה FxCop בזמן publish, לא עוזבת אותי,

כי אני ממשיך לכתוב אודותיו.

בכל מקרה, המשכתי קצת לשחק עם הקוד, וגיליתי משהו מעניין, החוק שמחייב אותנו, לממש case עבור כל האפשריות ב enum, עובד רק עם ממשנו יותר מ case אחד, במדה וממשנו רק case אחד, ה Code Analysis יתעלם לגמרי מכל מה שאנחנו כותבים והוא יעביר את הקוד קומפילציה,

אז כדי להבין מה קורה, כתבתי את הקוד הבא, והסתכלתי ב reflector, וגיליתי דברים חדשים,

 

    1     public void f2(MyEnum myEnum)

    2     {

    3         switch (myEnum)

    4         {

    5             case MyEnum.A:

    6                 Console.WriteLine();

    7                 break;

    8             case MyEnum.B:

    9                 Console.WriteLine();

   10                 break;

   11             case MyEnum.C:

   12                 Console.WriteLine();

   13                 break;

   14             default:

   15                 Console.WriteLine();

   16                 break;

   17         }

   18     }

   19 

   20     public void f1(MyEnum myEnum)

   21     {

   22         switch (myEnum)

   23         {

   24             case MyEnum.A:

   25                 Console.WriteLine();

   26                 break;

   27             default:

   28                 Console.WriteLine();

   29                 break;

   30         }

   31     }

   32 }

 
כעת נסתכל מה הקומפיילר באמת עושה, נפתח את ה Refloctor, ונראה מה כתוב שם:
 
 אז הנה הקוד של f2 שבו אנחנו עושים מעבר על יותר מ case אחד:
 
Reflector1
 
 
כמובן בדיוק כמו שאנו מצפים, בלוק של switch שעושה בדיוק מה שכתבנו בקוד,
אבל נציץ על הקוד שמיוצר מ f1, שבו אנחנו עושים case רק על מקרה אחד (ה default לא נחשב)
 
reflactor2
 
אופה, אין שמץ של switch, יש בלוק if רגיל,
מסתבר שמישהו השקיע מחשבה וזמן, כדי לבדוק האם אנחנו עושים case רק על אחד,
לא ברור לי למה, מה היתרון שבלוק if נותן לנו, למה אי אפשר היה להשאיר את זה כ switch,
מה שאני כן יודע, זה שזה דופק לי את ה ForceSwitch, שכתבתי בעמל רב בפוסט הקודם,
 
אשמח אם למישהו יהיה פיתרון.
פורסם: Dec 21 2008, 02:50 PM by Shlomo | with 6 comment(s)
תגים:,

תוכן התגובה

Rotem Bloom כתב/ה:

היי שלמה,

האמת שבהתחלה חשבתי שמי שעושה לך את השינוי בקוד הוא ה-JIT ולכן ניסיתי לשלוט עליו בעזרת:

[assembly: DebuggableAttribute(false, true)]

שזה אומר בעצם:

לא לאפשר JIT TRACKING

ולא לעשות JIT OPTIMIZATION

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

מעניין באמת אם יש דרך.

# December 21, 2008 4:39 PM

Rotem Bloom כתב/ה:

דבר נוסף שהוא מעט מוזר זה שבדרך כלל ידוע ש: SWITCH הוא יותר מהיר מאשר ELSE IF ולכן לא ברור מדוע הפקודה הוחלפה.

מה שנראה לי הכי הגיוני זה שאולי במקרה שאין עוד אפשרויות ב-SWITCH אז IF הוא יותר יעיל ולכן הקומפיילר מחליף את המימוש למשהו יעיל יותר, אבל זו רק השערה.

מה אתה אומר?

# December 21, 2008 4:43 PM

Shlomo כתב/ה:

ההתנהגות באמת מוזרה, צריך לחפש מישהו שבאמת מבין בדברים האלו, אני אנסה לשאול את סשה

# December 21, 2008 5:26 PM

anonymous כתב/ה:

מוזר, האם זה קורה במצב של Debug?

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

# December 21, 2008 8:43 PM

Shlomo כתב/ה:

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

אני אשתף אותכם בממצאים

# December 21, 2008 9:25 PM

שלמה גולדברג כתב/ה:

אז דברנו על זה שהקומפיילר מרגיש חופשי לשחק עם הקוד שלנו איך שנראה לו, ולהפוך בלוקים של switch לבלוקים

# December 21, 2008 10:15 PM
שלח תגובה

(שדה חובה)  

(שדה חובה)  

(אופציונלי)

(שדה חובה) 

Please add 2 and 6 and type the answer here:


Enter the numbers above: