Scroll to marked position
حافظه در دات‌نت چطور کار می‌کند؟
وقتی شما یک برنامه می‌نویسید، مثلاً در C#، برنامه‌تان نیاز به فضایی در حافظه (RAM) دارد تا داده‌ها رو ذخیره کند.
دات‌نت دو نوع حافظه اصلی دارد:
                
                    int number = 10; // روی Stack ذخیره می‌شود
                    Person person = new Person(); // شیء جدید در Heap ساخته می‌شود
                
            

Garbage Collector (GC) چیست؟
وقتی شما یک شیء جدید در Heap می‌سازید، حافظه اختصاص داده می‌شود. اما اگر این شیء دیگر مورد نیاز نباشد، باید حافظه آزاد شود. اینجا GC وارد عمل می‌شود!
GC مثل یک خدمتکار هوشمند است که:

GC چطور کار می‌کند؟
GC در سه مرحله اصلی کار می‌کند:

نسل‌های حافظه (Generations)
برای بهینه‌سازی، GC از سه نسل (Generation) استفاده می‌کند:
✅ هرچه نسل بالاتر باشد، دفعات پاک‌سازی کمتر است (چون احتمالاً مهم هستند).
✅ Gen 0 بیشترین پاک‌سازی را دارد (چون اشیاء موقت زیادی دارد).

چرا GC عالی است؟
اما یک نکته:
⚠️ GC همیشه فوراً حافظه را آزاد نمی‌کند (مگر وقتی واقعاً نیاز باشد یا حافظه کم شود).

مثال ساده از GC در عمل
                
                    void CreateObjects()
                    {
                        // شیء جدید در هیپ ساخته می‌شود
                        Person person1 = new Person(); 
                        
                        // ارجاع جدید به همان شیء
                        Person person2 = person1;
                        
                        // حالا person1 را null می‌کنیم، اما شیء هنوز در حافظه است (چون person2 ارجاع دارد)
                        person1 = null;
                        
                        // حالا person2 هم null می‌شود، شیء دیگر ارجاعی ندارد
                        person2 = null;
                        
                        // حالا GC می‌تواند این شیء را پاک کند (البته نه لزوماً بلافاصله!)
                    }
                
            

چه موقع GC اجرا می‌شود؟
⚠️ استفاده از GC.Collect معمولاً توصیه نمی‌شود، مگر در موارد خاص!

منابع مدیریت‌شده (Managed) vs منابع غیرمدیریت‌شده (Unmanaged)

چرا Dispose مهم است؟
وقتی از منابع غیرمدیریت‌شده استفاده می‌کنید، باید حتماً آن‌ها را بسته (Release) کنید، وگرنه:
❌ حافظه مصرف شده آزاد نمی‌شود (Memory Leak).
❌ ممکن است فایل‌ها قفل شوند و برنامه‌های دیگر نتوانند از آن‌ها استفاده کنند.
❌ اتصالات دیتابیس باز می‌مانند و پس از مدتی سرور دیتابیس از کار می‌افتد!
✅ راه‌حل: استفاده از IDisposable و الگوی Dispose.

IDisposable چیست؟
این یک اینترفیس است که فقط یک متد دارد:
                
                    public interface IDisposable
                    {
                        void Dispose();
                    }
                
            
هر کلاسی که این اینترفیس را پیاده‌سازی کند، باید منابع غیرمدیریت‌شده را در Dispose آزاد کند.
مثال: کلاس FileStream (استفاده از Dispose)
                
                    using (FileStream file = File.Open("test.txt", FileMode.Open))
                    {
                        // کار با فایل
                    } // اینجا به طور خودکار file.Dispose() فراخوانی می‌شود، حتی اگر خطایی رخ دهد!
                
            
یا به صورت دستی:
                
                    FileStream file = null;
                    try
                    {
                        file = File.Open("test.txt", FileMode.Open);
                        // کار با فایل
                    }
                    finally
                    {
                        file?.Dispose(); // مطمئن می‌شویم فایل حتما بسته می‌شود
                    }
                
            

using چطور کار می‌کند؟
وقتی شما کدی مثل این می‌نویسید:
                
                    using (var resource = new SomeDisposableResource())
                    {
                        // کار با resource
                    } // اینجا Dispose() به صورت خودکار فراخوانی می‌شود                    
                
            
کامپایلر C# آن را به این شکل تبدیل می‌کند:
                
                    var resource = new SomeDisposableResource();
                    try
                    {
                        // کار با resource
                    }
                    finally
                    {
                        resource.Dispose(); // حتی اگر خطا رخ دهد، Dispose فراخوانی می‌شود
                    }                
                
            
نکات کلیدی درباره using: مثال: استفاده با چند IDisposable
                
                    using (var file = File.OpenRead("data.txt"))
                    using (var reader = new StreamReader(file))
                    {
                        string content = reader.ReadToEnd();
                    } // اول reader.Dispose() و سپس file.Dispose() فراخوانی می‌شود               
                
            

Go to top