مدیریت حافظه و 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» با تمرکز بر ساختارهای اصلی زبان، الگوهای صحیح استفاده و خطاهای رایج بررسی شد. تسلط بر این مفاهیم زمینه لازم برای اتصال موضوع به فصلهای بعدی و طراحی کدهای خواناتر، قابل نگهداری و قابل تست را فراهم میکند.