Skip to main content
Class Structure refers to the organization and design of classes in C#, including their members, relationships, and construction/destruction mechanisms. It encompasses how classes are built, initialized, and cleaned up, providing the blueprint for creating objects in object-oriented programming.

Constructor Chaining

Constructor chaining allows one constructor to call another within the same class, promoting code reuse and reducing duplication.
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Email { get; set; }

    // Default constructor chains to parameterized constructor
    public Person() : this("Unknown", 0, "[email protected]")
    {
    }

    // Primary constructor with all parameters
    public Person(string name, int age, string email)
    {
        Name = name;
        Age = age;
        Email = email;
    }

    // Partial parameter constructor chains to primary constructor
    public Person(string name, int age) : this(name, age, $"{name.ToLower()}@example.com")
    {
    }
}

// Usage example
var person1 = new Person(); // Uses default constructor chain
var person2 = new Person("Alice", 25); // Chains to primary constructor
Constructor chaining follows the DRY principle, reducing code duplication and making maintenance easier.

Destructors

Destructors (finalizers) are special methods that automatically clean up resources when an object is garbage collected. They’re called automatically by the CLR.
public class ResourceHandler
{
    private FileStream _fileStream;
    private bool _disposed = false;

    public ResourceHandler(string filePath)
    {
        _fileStream = File.OpenRead(filePath);
        Console.WriteLine("Resource acquired");
    }

    // Destructor (finalizer)
    ~ResourceHandler()
    {
        Dispose(false);
        Console.WriteLine("Destructor called");
    }

    // Proper disposal pattern
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this); // Prevents finalizer call
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                // Managed resources
                _fileStream?.Dispose();
            }
            // Unmanaged resources cleanup
            _disposed = true;
        }
    }
}
Destructors should implement the Dispose pattern properly to ensure efficient resource cleanup and prevent memory leaks.

Static Constructors

Static constructors initialize static members of a class and are called automatically before any static members are accessed or any instances are created.
public class ConfigurationManager
{
    private static readonly Dictionary<string, string> _settings;
    private static readonly DateTime _initializationTime;

    // Static constructor
    static ConfigurationManager()
    {
        _settings = new Dictionary<string, string>();
        _initializationTime = DateTime.Now;
        
        // Load configuration from file
        LoadSettings();
        Console.WriteLine("Static constructor executed");
    }

    private static void LoadSettings()
    {
        _settings["Database"] = "Server=localhost;Database=MyApp";
        _settings["ApiKey"] = "secret-key-123";
    }

    public static string GetSetting(string key)
    {
        return _settings.TryGetValue(key, out var value) ? value : null;
    }

    public static DateTime InitializationTime => _initializationTime;
}

// Usage - static constructor is called automatically
var dbSetting = ConfigurationManager.GetSetting("Database");

Why Class Structure is Important

  • Maintainability - Constructor chaining follows the DRY principle, reducing code duplication
  • Resource Management - Proper destructor implementation ensures efficient resource cleanup
  • Reliability - Static constructors provide controlled initialization, adhering to the Single Responsibility Principle

Advanced Nuances

Lazy Initialization with Static Constructors

Static constructors combined with Lazy\<T\> can provide thread-safe lazy initialization:
public class LazySingleton
{
    private static readonly Lazy<LazySingleton> _instance = 
        new Lazy<LazySingleton>(() => new LazySingleton());
    
    private LazySingleton() { }
    
    public static LazySingleton Instance => _instance.Value;
}

Exception Handling in Constructors

Constructors should handle exceptions carefully to avoid partially constructed objects:
public class DatabaseConnection
{
    private readonly SqlConnection _connection;
    
    public DatabaseConnection(string connectionString)
    {
        try
        {
            _connection = new SqlConnection(connectionString);
            _connection.Open(); // Could throw exception
        }
        catch
        {
            _connection?.Dispose(); // Cleanup if initialization fails
            throw; // Re-throw to prevent partial construction
        }
    }
}
Best Practice: Always clean up partially constructed objects in the catch block before re-throwing exceptions.

Roadmap Context

Class Structure serves as the foundation for the “Object-Oriented Programming” section. Mastering class structure unlocks:
  • Inheritance patterns - Understanding base class construction
  • Disposable pattern - Advanced resource management techniques
  • Singleton pattern - Static constructor applications
  • Factory patterns - Constructor design strategies

Build docs developers (and LLMs) love