فصل 32 از 40 درس 1 از 1

مدیریت حافظه و IDisposable

مدیریت حافظه و IDisposable

بخشی از آموزش جامع C# و .NET 10

محتوای درس مدیریت حافظه و IDisposable

C# حافظه مدیریت‌شده را با Garbage Collector اداره می‌کند، اما Resourceهای خارجی مانند File Handle و Socket نیاز به آزادسازی قطعی دارند. شناخت Stack، Heap و IDisposable در کارایی و پایداری برنامه مهم است.

۱. Value و Reference Type

Value Type معمولاً مقدار را مستقیماً حمل می‌کند و Reference Type ارجاع به Object را نگه می‌دارد. جزئیات محل ذخیره به Context و Runtime وابسته است و نباید با قواعد ساده‌سازی‌شده اشتباه شود.

مثال

int a=1,b=a;b=2; var l1=new List<int>{1};var l2=l1;l2.Add(2);Console.WriteLine($"{a}/{l1.Count}");

در این مثال، مفهوم «Value و Reference Type» در یک قطعه کد مستقل نمایش داده شده است. مقدارها و نام‌ها عمداً ساده انتخاب شده‌اند تا رفتار اصلی قابل مشاهده باشد؛ در پروژه واقعی همین الگو با مدل دامنه، اعتبارسنجی و مدیریت خطای متناسب ترکیب می‌شود.

۲. Garbage Collector

GC Objectهای مدیریت‌شده غیرقابل دسترسی را جمع‌آوری می‌کند و نسل‌ها برای بهینه‌سازی Collection استفاده می‌شوند.

مثال

var data=new byte[1024]; Console.WriteLine(GC.GetGeneration(data));

در این مثال، مفهوم «Garbage Collector» در یک قطعه کد مستقل نمایش داده شده است. مقدارها و نام‌ها عمداً ساده انتخاب شده‌اند تا رفتار اصلی قابل مشاهده باشد؛ در پروژه واقعی همین الگو با مدل دامنه، اعتبارسنجی و مدیریت خطای متناسب ترکیب می‌شود.

۳. IDisposable

Resourceهای unmanaged یا Wrapperهای آن‌ها باید در زمان مشخص Dispose شوند.

مثال

using FileStream s=File.OpenRead("data.bin"); Console.WriteLine(s.Length);

در این مثال، مفهوم «IDisposable» در یک قطعه کد مستقل نمایش داده شده است. مقدارها و نام‌ها عمداً ساده انتخاب شده‌اند تا رفتار اصلی قابل مشاهده باشد؛ در پروژه واقعی همین الگو با مدل دامنه، اعتبارسنجی و مدیریت خطای متناسب ترکیب می‌شود.

۴. using

using statement و using declaration تضمین می‌کنند Dispose حتی در رخداد Exception انجام شود.

مثال

using var reader=new StringReader("hello"); Console.WriteLine(reader.ReadLine());

در این مثال، مفهوم «using» در یک قطعه کد مستقل نمایش داده شده است. مقدارها و نام‌ها عمداً ساده انتخاب شده‌اند تا رفتار اصلی قابل مشاهده باشد؛ در پروژه واقعی همین الگو با مدل دامنه، اعتبارسنجی و مدیریت خطای متناسب ترکیب می‌شود.

۵. Finalizer

Finalizer مکانیزم پشتیبان برای Resource unmanaged است و استفاده مستقیم از آن در کد روزمره نادر است.

مثال

class Resource { ~Resource(){ /* last resort cleanup */ } }

در این مثال، مفهوم «Finalizer» در یک قطعه کد مستقل نمایش داده شده است. مقدارها و نام‌ها عمداً ساده انتخاب شده‌اند تا رفتار اصلی قابل مشاهده باشد؛ در پروژه واقعی همین الگو با مدل دامنه، اعتبارسنجی و مدیریت خطای متناسب ترکیب می‌شود.

۶. مثال‌های عملی

using var stream = File.OpenRead("data.bin");
         Console.WriteLine(stream.Length);

این نمونه عملی چند مفهوم فصل را در کنار هم قرار می‌دهد و برای مشاهده رفتار واقعی کد قابل اجرا و تغییر است.

public sealed class ResourceHolder : IDisposable
         {
             private readonly Stream _stream;
         
             public ResourceHolder(Stream stream) => _stream = stream;
         
             public void Dispose() => _stream.Dispose();
         }

این نمونه عملی چند مفهوم فصل را در کنار هم قرار می‌دهد و برای مشاهده رفتار واقعی کد قابل اجرا و تغییر است.

۷. خطاهای رایج

• تکیه به GC برای بستن فایل یا Connection

• فراخوانی دستی Dispose در چند مسیر به‌جای using

• پیچیده کردن کد با Finalizer بدون Resource unmanaged مستقیم

۸. نکات اجرایی

• نام‌ها، Typeها و Methodها را متناسب با مفهوم دامنه و بدون ابهام انتخاب کنید.

• هشدارهای کامپایلر و Nullable را بدون بررسی خاموش نکنید.

• منطق هر بخش را تا حد امکان کوچک، قابل تست و مستقل از I/O غیرضروری نگه دارید.

۹. تمرین عملی

کلاسی بسازید که Stream را دریافت کند، عملیات خواندن انجام دهد و IDisposable را به‌صورت صحیح پیاده‌سازی کند.

۱۰. جمع‌بندی

در این فصل، مبانی «مدیریت حافظه و IDisposable» با تمرکز بر ساختارهای اصلی زبان، الگوهای صحیح استفاده و خطاهای رایج بررسی شد. تسلط بر این مفاهیم زمینه لازم برای اتصال موضوع به فصل‌های بعدی و طراحی کدهای خواناتر، قابل نگهداری و قابل تست را فراهم می‌کند.