أهلًا بك،
تنقسم العناصر في لغة #C إلى نوعين:
Value-Based Types: العناصر التي تمرر بالقيمة.
Reference-Based Types: العناصر التي تمرر بالمرجعية.
Value-Based Types
ويدخل تحت هذا النوع جميع البيانات الرقمية (مثل Integer و Double وغيرها)وكذلك العدادات Enumerations وأيضا Structures.
ويتم تسجيل بيانات هذا النوع في القسم الأول من الذاكرة وهو Stack. ولذلك يتم إزالة هذه البيانات من الذاكرة فور انتهاء قطعة الكود التي تستخدم هذا النوع.
وعند إسنادك لقيمة عنصر من نوع Value Type إلى عنصر آخر مماثل, يتم إنشاء نسخة من قيمة العنصر الأول إلى العنصر الثاني.
وهذه القاعدة تنطبق أيضا على Structures و Enumerations كما قلنا سابقا.
فعند إسناد متغير أول إلى متغير أخر تصبح عندنا نسختان من القيمة في المتغير الاول وهذا هو معنى Value-Based Types.
Reference-Based Types
يعتبر هذا النوع ضد النوع الأول بشكل كامل حيث يدخل تحت هذا النوع جميع الـ Classes, يتم تسجيل هذا النوع في المنطقة الثانية في الذاكرة وهي Heap. ولا تستطيع تحديد متى سيتم إلغاء هذا النوع من الذاكرة حيث أن Garbage Collector (GC) هي المسؤولة عن إلغائه (سيتم شرح GC لاحقا).
ويظهر الفرق واضحا في بين النوعين في أن عند إسنادك أي عنصر من هذا النوع إلى عنصر آخر يتم إنشاء نسخة من النوع الأول وتتغير النسخة المنشأة بتغيير النسخة الأصلية والعكس صحيح, أي أنك لا تستطيع إنشاء نسختين منفصلتين, ولكن تنشئ نسخة مرتبطة بالنسخة الأولى.
قاعدة: يمكن لـ Value Type أن تحتوي على Reference Type. وتنطبق جميع قواعد Reference Types على الـ Reference Type الداخلية.
مقارنة بين Value Types و Reference Types
التالي هو مقارنة بين النوعين باختصار:
أين يتم تخزين بيانات هذا النوع؟
Value-Types: في الجزء الأول من الذاكرة: Stack
Reference-Types: في الجزء الآخر من الذاكرة: Heap
كيف يتم الإسناد إلى هذا النوع؟
Value-Types: يتم إنشاء نسخة من القيم الداخلية يتم إسنادها إلى النسخة الأخرى
Reference-Types: يتم إنشاء نسخة مرجعية من النسخة الأصلية تتغير بتغيير النسخة الأصلية والعكس صحيح
ما هي أنواع البيانات التي تدخل تحت هذا النوع؟
Value-Types: جميع البيانات الرقمية وكذلك النصية وأيضا Enumerations و Structures
Reference-Types: Classes
ما هو العنصر الذي ينحدر/يتوارث (inherits) منه هذا النوع؟
Value-Types: هذا النوع ينحدر/يتوارث (inherits) من System.ValueType
Reference-Types: هذا النوع ينحدر/يتوارث (inherits) من System.Object
هل يمكن أن يكون هذا النوع قاعدة Base للأنواع الأخرى؟ بمعنى آخر: هل يمكن أي نوع آخر أن ينحدر/يتوارث من هذا النوع؟
Value-Types: لا, لا يمكن ذلك
Reference-Types: نعم, يمكنك ذلك إلا في بعض الحالات كتحديد الـ Class كـ NotInheritable (في VB.NET) أو sealed (في C#)
عند تمرير هذا النوع كمعامل Argument كيف يمرر؟
Value-Types: تمرر نسخة من قيمة هذا النوع كمدخلات
Reference-Types: يمرر العنصر نفسه وليس نسخة منه
هل يمكننا إزالة هذا النوع من الذاكرة باستخدام Object.Finalize() (سوف يتم شرح هذه الدالة لاحقا)؟
Value-Types: لا, حيث أن هذا النوع لا يتم تسجيله في Heap مطلقا
Reference-Types: نعم, مباشرة
متى سوف يتم تحرير الذاكرة الخاصة بهذا النوع؟
Value-Types: عند انتهاء قطعة الكود التي تستخدم هذا النوع
Reference-Types: عند إجراء عملية Garbage Collection (سوف يتم شرح هذه العملية لاحقا)
لأمثلة وشرح أوسع يمكنك متابعة المصدر
ال stack و ال heap هماطرق للتعامل مع الذاكره ولهم أماكن
ال stack هو طريقه معينه فى ترتيب العناصر حيث يتم اضافه العنصر الجديد خلف او اعلى جميع العناصر القديمه ولا يمكنك الوصول الى اى عنصر غير العنصر الاخير ثم العنصر قبل الاخير يمكنك تخيل الموضوع بتكديس او وضع مجموعه كتب فوق بعضها حيث لا يمكنك الوصول الى اول كتاب من اسفل، فقط يمكنك الوصول الى اول كتاب من اعلى ثم الذى يليه وهكذا بشكل عام يدعم ال stack عمليتين funcion العمليه الاولى هى الاضافه الى اعلى push العمليه الثانيه هى الحذف من الاعلىpop
الheap يمكنك اعتبارها raw memory اى الذاكره بدون اى ترتيب ويمكتك الوصول الى اى مكان وما يتم انشاءه بال heap يظل به حتى ينتهى البرنامح على عكس ال stack ما يتم انشاءه به يظل حتى يتم عمل pop له
بالتوفيق..