צלילה עמוקה: סוגי ערך והתייחסות ב- .Net

סוגים ב- Microsoft .Net יכולים להיות סוג ערך או סוג הפניה. בעוד סוגי הערך מאוחסנים בדרך כלל בערימה, סוגי הפניה מאוחסנים בערמה המנוהלת.

סוג ערך נובע מ- System.ValueType ומכיל את הנתונים בתוך הקצאת זיכרון משלו. במילים אחרות, למשתנים או אובייקטים או סוגי ערכים יש עותק משלהם של הנתונים.

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

שים לב שבניגוד לסוג הפניה, אינך יכול להפיק סוג ערך, ולא ניתן להקצות ערך null ישירות לסוג ערך. באפשרותך להקצות ערך null לסוג ערך רק על ידי ניצול של סוגי nullable - תכונה שנוספה לגרסאות החדשות יותר של .Net Framework. כאשר סוג ערך מועתק לאחר, הערך מועתק. לפיכך, ניתן לתפעל את הערכים שבהם ללא תלות באחר - שינוי באחד אינו משפיע על האחר. נהפוך הוא, כאשר אתה מעתיק סוג הפניה לאחר, ההפניה מועתקת. אם אתה משנה אחד מהם, גם השני מושפע. כדוגמה, אם אחת מההפניות מוגדרת לאפס, גם השנייה הופכת לאפסית.

מיקומי אחסון

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

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

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

עוברים לפי ערך ועוברים לפי הפניה

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

 static void Increment(int i)

        {

            i = i + 1;

        }

        static void Main()

        {

            int x = 1;

            Increment(x);

            Console.WriteLine("The value of x is: " +x);

            Console.Read();

        }

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

static void Increment(ref int i)

        {

            i = i + 1;

        }

        static void Main()

        {

            int x = 1;

            Increment(ref x);

            Console.WriteLine("The value of x is: " +x);

            Console.Read();

        }

כאשר הקוד לעיל מבוצע, ההודעה "הערך של x הוא: 2" תוצג במסוף.

אגרוף ואי אגרוף

ההמרה של סוג ערך לסוג ייחוס מכונה אגרוף. Unboxing הוא בדיוק ההפך - הוא מוגדר כתהליך המרה של סוג התייחסות לסוג ערך. קטע הקוד הבא ממחיש אגרוף ואי-אגרוף ב- C #.

int i = 100;

Object obj = i; //Boxing

i = (int) obj; //Unboxing