تفاوت‌های Reference Type و Value Type

سی‌شارپ (C#)، تفاوت Value Type و Reference Type، اصول برنامه‌نویسی 1404/5/28
نویسنده: مدرس بهمن آبادی

 تفاوت‌های Reference Type و Value Type در سی‌شارپ

مقدمه

در سی‌شارپ، داده‌ها به دو دسته‌ی اصلی تقسیم می‌شوند:

  1. Value Type (انواع مقداری)

  2. Reference Type (انواع ارجاعی)

شناخت این تفاوت‌ها یکی از بنیادی‌ترین مفاهیم در برنامه‌نویسی دات‌نت است. اگر این تفاوت‌ها را ندانیم، به راحتی با باگ‌های عجیب و مشکلات کارایی روبرو می‌شویم.

1. محل ذخیره‌سازی داده‌ها

  • Value Type: مقدار واقعی در Stack ذخیره می‌شود.

  • Reference Type: یک آدرس (Reference) در Stack نگه داشته می‌شود و داده‌ی واقعی در Heap ذخیره می‌شود.

 مثال:

2. نحوه کپی شدن داده‌ها

  • Value Type: هنگام انتساب، یک کپی مستقل ساخته می‌شود.

  • Reference Type: هنگام انتساب، فقط آدرس کپی می‌شود.

 مثال:

3. Null پذیری

  • Value Type ها به صورت پیش‌فرض null نیستند.

  • Reference Type ها می‌توانند null باشند.

 مثال:

4. مقایسه (==)

  • Value Type: مقایسه بر اساس مقدار انجام می‌شود.

  • Reference Type: مقایسه پیش‌فرض بر اساس آدرس حافظه است (مگر اینکه Equals یا == Overload شده باشد).

 مثال:

5. انواع پیش‌فرض

  • Value Type ها: همه‌ی انواع عددی (int, double, bool, char, struct, enum).

  • Reference Type ها: همه‌ی کلاس‌ها (class)، آرایه‌ها، string، interface, delegate.

6. Performance (کارایی)

  • Value Type ها سریع‌تر هستند چون در Stack ذخیره می‌شوند و مدیریت‌شان ساده است.

  • Reference Type ها به دلیل ذخیره در Heap نیازمند Garbage Collector هستند و هزینه‌ی بیشتری دارند.

اما! 
اگر struct خیلی بزرگ باشد (مثلاً شامل ده‌ها فیلد)، کپی شدن مکرر آن می‌تواند کندتر از کلاس باشد.

7. رفتار در متدها

  • Value Type: مقدار کپی می‌شود، تغییرات داخل متد اثری روی بیرون ندارد.

  • Reference Type: آدرس پاس می‌شود، تغییرات روی شیء بیرونی هم اعمال می‌شود.

 مثال:

8. Boxing و Unboxing

هنگامی که یک Value Type به object (یا interface) تبدیل می‌شود، باید Boxing شود (انتقال از Stack به Heap).
این عملیات پرهزینه است و در کارایی تأثیر می‌گذارد.

 مثال:

9. Nullable و Reference Type ها

  • Value Type ها به طور پیش‌فرض Nullable نیستند ولی می‌توان از Nullable<T> یا T? استفاده کرد.

  • Reference Type ها به صورت پیش‌فرض Nullable هستند.

  • از C# 8 به بعد، می‌توان با Nullable Reference Types جلوی خطاهای NullReferenceException را گرفت.

10. سناریوهای کاربردی

  • اگر داده کوچک و تغییرناپذیر است (مثل مختصات یک نقطه)، struct (Value Type) بهتر است.

  • اگر داده بزرگ و دارای رفتار (متدها و منطق) است، class (Reference Type) مناسب‌تر است.

نتیجه‌گیری

شناخت تفاوت بین Value Type و Reference Type برای هر برنامه‌نویس سی‌شارپ ضروری است، چون:

  • روی Performance و مدیریت حافظه تأثیر مستقیم دارد.

  • مانع از بروز باگ‌های سخت و غیرمنتظره می‌شود.

  • به طراحی درست Domain Model و API کمک می‌کند.

در دوره جامع برنامه نویسی وب مهندس بهمن آبادی تمامی این موارد کامل توضیح داده شده است.