Phase 7 of 30 · Topic 7.5

Class Memory Hierarchy & Struct Boxing Traps

1Concept

Calling non-overridden `object` methods (`ToString`, `GetType`) on a struct causes immediate heap boxing. Always override `ToString`, `Equals`, and `GetHashCode` on structs to maintain zero allocation.

2Architecture Diagram

Struct without Override:
struct.ToString() ──> Boxes struct onto Heap ──> Virtual dispatch (GC Allocation!)

Struct with Override:
struct.ToString() ──> Direct inline struct method execution (Zero GC Allocation!)

3Code Example

C# 13 & .NET 9
using System;

public struct OptimizedPoint : IEquatable<OptimizedPoint>
{
    public int X;
    public int Y;

    public bool Equals(OptimizedPoint other) => X == other.X && Y == other.Y;
    public override bool Equals(object? obj) => obj is OptimizedPoint other && Equals(other);
    public override int GetHashCode() => HashCode.Combine(X, Y);
    public override string ToString() => $"({X}, {Y})";
}

public class StructBoxingTrapDemo
{
    public static void Main()
    {
        var pt = new OptimizedPoint { X = 100, Y = 200 };
        Console.WriteLine($"Point: {pt.ToString()} (No boxing occurs)");
    }
}

4Expected Output

Point: (100, 200) (No boxing occurs)

5Key Takeaways

  • Always implement `IEquatable<T>` on every custom struct.
  • Always override `ToString()` on structs to prevent boxing.
  • Never call `.GetType()` on a struct in high-performance loops (use `typeof(T)`).