Memory Management and Execution on Windows — C# (.NET)

Last updated: December 13, 2025
Author: Paul Namalomba
- SESKA Computational Engineer
- Software Developer
- PhD Candidate (Civil Engineering Spec. Computational and Applied Mechanics)

Contact: kabwenzenamalomba@gmail.com
Website: paulnamalomba.github.io

Language: C# Runtime: .NET License: MIT

Overview

This guide explains how C# and the .NET runtime (CoreCLR/CLR) implement memory management and execution semantics on Windows. Covering value vs reference types, stack vs heap storage, copy semantics, and nullability features (nullable reference types, Nullable<T>), plus examples and best practices.

Contents


Windows — Build & Run (PowerShell / Command Prompt)

powershell # Create console project dotnet new console -n MemoryDemo cd MemoryDemo # Replace Program.cs with main.cs if needed, then run dotnet run


Overview

This guide explains how C# and the .NET runtime (CoreCLR/CLR) implement memory management and execution semantics on Windows. Covering value vs reference types, stack vs heap storage, copy semantics, and nullability features (nullable reference types, Nullable<T>), plus examples and best practices.


Contents


1) Data Structures — Value-Type vs Reference-Type

Table comparison:

Aspect Value Types Reference Types
Examples int, struct Point class Person, string
Storage Inline (stack or embedded) Managed heap (GC)
Passing Copy of value Copy of reference
Nullability Nullable<T> (int?) Can be null, but nullable reference types provide annotations

Example:

struct Point { public int X; public int Y; }
class Person { public string Name { get; set; } }

void Demo() {
    Point p1 = new Point { X = 1, Y = 2 };
    Point p2 = p1; // copy

    Person a = new Person { Name = "Paul" };
    Person b = a; // reference copy
    b.Name = "Changed"; // a.Name == "Changed"
}

Notes: - string is a reference type but immutable: assignment yields reference copy; modifications produce new strings.


2) Storage — Stack vs Heap & Garbage Collector

Windows/.NET specifics: - The CLR uses the OS virtual memory and the GC has options (Workstation vs Server) and settings in runtimeconfig.json. - Use GC.Collect only in rare cases; prefer letting runtime manage memory.

Example demonstrating GC behavior:

class Demo {
    static void CreateObjects() {
        for (int i=0;i<100000;i++) {
            var o = new object();
        }
    }

    static void Main() {
        CreateObjects();
        GC.Collect(); // forces collection (not usually recommended)
    }
}

Tips: - Implement IDisposable and using for deterministic unmanaged resource cleanup. - Use WeakReference<T> for cache-like scenarios where you don't want to keep objects alive.


3) Copy Semantics — Shallow vs Deep

Example (shallow vs deep):

class Book { public string Title; public List<string> Authors = new(); }

void Demo() {
    var b1 = new Book { Title = "A", Authors = new List<string>{"X"} };
    var b2 = b1; // shallow (reference copy)
    b2.Authors.Add("Y"); // b1.Authors also changed

    // Deep copy (manual)
    var b3 = new Book { Title = b1.Title, Authors = new List<string>(b1.Authors) };
}

Best practices: - Prefer immutable types or make deep copies when necessary. - Use MemberwiseClone carefully; implement custom cloning when needed.


4) Nullability

Example:

#nullable enable
string? maybe = null;
if (maybe != null) Console.WriteLine(maybe.Length);

int? maybeInt = null;
if (maybeInt.HasValue) Console.WriteLine(maybeInt.Value);

Tips: - Enable nullable reference types in csproj (<Nullable>enable</Nullable>). - Use null-coalescing ?? and ?. for safe access.


Examples — Runnable Snippets

Program.cs:

using System;
using System.Collections.Generic;

class Program {
    static void Main() {
        // Value vs Reference
        var p1 = new Point { X = 1, Y = 2 };
        var p2 = p1; // copied

        var book1 = new Book { Title = "C#" };
        var book2 = book1; // reference copy
        book2.Title = "Changed";
        Console.WriteLine(book1.Title); // "Changed"

        // Nullable
        string? s = null;
        Console.WriteLine(s ?? "(null)");
    }
}

struct Point { public int X; public int Y; }
class Book { public string Title; public List<string> Authors = new(); }

Run with dotnet run in project folder.


Windows/.NET Specific Notes


References

End of C# guide.