// Chapter 9 // Garbage Collection // .Net Core // 5 step process / workflow /* * 1. Memory Allocation > object new Contacts() * 2. Object Lifetime > exit() eligible for GC * 3. Process > automated that checks objects to be disposed "periodically scans" eligible objects for disposal * 3a. Manually call the Garbage Collection Class * 4. Automatic Execution - CLR Common Language Runtime * 5. Generational Collections - LIFO younger objects are disposed of before older objects */ // Finalizers /* * Use to execute anything that needs to be done with an object BEFORE GC.Collect() * Text Files open() BUT no built in close() * File IO handler * database connections * unmanaged memory / not managed by .Net */ // Key Principles of Finalizers /* * Requirement > ~ClassPrefix ~Order() BUT no params * They are never called explicitly by user code * They run whenever they want "exact schedule" * Very heavy on memory resources "resource intensive" * A better option IDisposable Interface */ // IDisposable Interface // Class : Interface // ClassName : IDisposable /* Dispose() is easier on resources than Finalizers * A user CAN call Dispose() in the code * "using" statement like a built in "exception" * */ // Unsafe Code /* Code than is not DIRECTLY managed in memory by .Net * unmanaged objects in memory (.Net non managed) * buffer (streaming) * anything that runtime either managed or unmanged that bypasses basic security checks RISK * hardware that is NOT memory that maps directly to memory ex. dlls * unsafe keyword */ public class Order : IDisposable { public string SKU { get; set; } public string Description { get; set; } public decimal Price { get; set; } private bool disposed = false; public Order(string sku, string description, decimal price) { SKU = sku; Description = description; Price = price; } // Constructor // unsafe buffer control/manipulation // defined // call it in Program public unsafe void UnsafeBuffer() { const int bufferSize = 5; byte[] buffer = new byte[bufferSize]; fixed (byte* ptr = buffer) { byte* current = ptr; // [] = [0] // [0] = [0,1] for (int i = 0; i < bufferSize; i++) { *current = (byte)(i+1); // Fill the buffer with 1-5 current++; //1+1 2 ptr 2 } // for } // fixed Console.WriteLine("Items in Buffer"); foreach (var item in buffer) { Console.WriteLine(item + " "); } Console.WriteLine(); } // Unsafe Buffer // IDisposable object public void Dispose() { Dispose(true); GC.SuppressFinalize(this); // Order Class } // Dispose() // if true run Dispose() if false run Finalizer protected virtual void Dispose(bool disposing) { if (!disposed) // !false it means run Dispose() { if (disposing) { Console.WriteLine("Release resources via Interface."); } // Console.WriteLine("Release resources via Finalizer."); // disposed = false disposed = true; // private attr Class } // if ! } // Dispose() bool return // Finalizer ~Order() { // log whatever running here Console.WriteLine($"Finalizing Order.SKU: {SKU}"); // object Console.WriteLine($"Finalizing Order.Description: {Description}"); Console.WriteLine($"Finalizing Order.Price: {Price}"); // stuff you do manually // close File // close db.conn // dispose unmanaged .Net memory } // ~Order } // Order class Program { static void Main(string[] args) { // Create some objects in memory Order order1 = new Order("1234", "Order 1", 25.50m); Order order2 = new Order("1252", "Order 2", 45.21m); // use the objects in memory Console.WriteLine("Order 1 Total: " + order1.Price); Console.WriteLine("Order 2 Total: " + order2.Price); // Make the objects in memory unused and eligible for garbage collection. // an assigned null value makes an object automatically eligible EVEN IF the program is still being executed. // call it thru instance of order order1.UnsafeBuffer(); order1 = null; // eligible order2 = null; // eligible // Do other stuff down here.... decimal cartTotal = 525.00m; decimal taxPerc = .07m; decimal CreditCardTotal = (cartTotal * taxPerc) + cartTotal; Console.WriteLine(CreditCardTotal); // Point in your program manually run GC // if safe code you should never have to do this GC.Collect(); // not typical in a program // Finalizer // like "wait timer" GC.WaitForPendingFinalizers(); // something that takes 1.4 seconds } // Main } // Program // Exit Code 0 or Exit Code 1