Class vs Struct


Introduction to Classes


A class in C# is a reference type, meaning that variables of this type store references (memory addresses) to objects rather than the actual object itself. It means that when a class is instantiated, memory is allocated to store the object's data.

When a class is declared:

When you define a class, you are essentially defining a new data type that can have properties (data) and methods (functions) associated with it.

Key Points

  1. Reference Type

    • A class is a reference type, meaning that when an instance of a class (an object) is created, the variable holding it does not contain the actual data. Instead, it holds a reference (or memory address) to where the data is stored in memory.
  2. Memory Allocation

    • When you instantiate a class using the new keyword, memory is allocated on the heap to store the object's data. The variable used to access this object holds a reference to this memory location.

Example

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

// Creating an instance of the Person class
Person person1 = new Person();
person1.Name = "Alice";
person1.Age = 30;

// Creating another reference to the same object
Person person2 = person1;

// Modifying the object through the second reference
person2.Age = 35;

// Both person1 and person2 refer to the same object
Console.WriteLine(person1.Age); // Output: 35
Console.WriteLine(person2.Age); // Output: 35

Explanation:

This behavior differs from value types (like int, float, struct), where the variable holds the actual data, and copying the variable creates a new copy of the data.

Understanding this distinction is crucial for managing memory and avoiding unintended side effects in your programs.

Metaphor:
A class is like an architectural blueprint for a house. The blueprint itself does not take up space, but once a house is built (instantiated), it occupies a physical location.

Practical Applications

Classes are beneficial when dealing with:

Example Use Case:
In an e-commerce system, a Customer class might be used to represent shoppers, containing attributes like Name, Email, and methods such as PlaceOrder().

Key Considerations

Introduction to Structs


A struct in C# is a value type, meaning that variables of this type hold the actual data rather than a reference to an object in memory.

Key Points

  1. Value Type

    • Unlike classes, structs store their actual data directly in the variable, not a reference.
    • When a struct is assigned to another variable, a copy of the data is made, meaning the two variables operate independently.
  2. Memory Allocation

    • Structs are allocated on the stack, which provides faster access compared to heap allocation.
    • They are suitable for small, short-lived objects that do not require complex behavior.

Example

public struct Point
{
    public int X { get; set; }
    public int Y { get; set; }
}

// Creating an instance of the struct
Point point1 = new Point();
point1.X = 10;
point1.Y = 20;

// Copying struct data to another variable
Point point2 = point1;

// Modifying the copied struct
point2.X = 50;

// Original struct remains unchanged
Console.WriteLine(point1.X); // Output: 10
Console.WriteLine(point2.X); // Output: 50

Explanation:


When to Use Structs

Structs are ideal for:

Example Use Case:
In a graphics application, a Color struct might be used to represent RGB values efficiently without unnecessary overhead.


Key Considerations

Differences Between Classes and Structs


Understanding the fundamental differences between classes and structs in C# is essential for making the right design decisions when developing applications.

Feature Class (Reference Type) Struct (Value Type)
Memory Allocation Allocated on the heap, accessed via reference Allocated on the stack, holds actual data
Copy Behavior Copies reference (points to the same object) Creates a new copy of the entire object
Performance Slower due to heap allocation and garbage collection Faster for small data due to stack allocation
Inheritance Supports inheritance ✅ Does not support inheritance ❌
Mutability Mutable by default Can be made immutable easily
Usage Best for complex objects with shared state Best for small, lightweight objects

Mutability in Classes and Structs

Mutability refers to whether or not the state (data) of an object can be changed after it is created.

Key Points:

  1. Mutable by Default (Classes)

    • In C#, class instances are mutable by default, meaning their properties and fields can be modified after creation without any special effort.

    • Example:

      public class Person
      {
          public string Name { get; set; }
          public int Age { get; set; }
      }
      
      Person person1 = new Person { Name = "Alice", Age = 30 };
      Console.WriteLine(person1.Age);  // Output: 30
      
      person1.Age = 35;  // The object's state is modified
      Console.WriteLine(person1.Age);  // Output: 35
      
    • Since classes are reference types, multiple references to the same object can result in unintended side effects, as all references will reflect any changes made.

  2. Can Be Made Immutable Easily (Structs)

    • Structs in C# can be made immutable by using the readonly modifier for fields and properties, ensuring their state cannot be changed after creation.
    • Example:
      public struct Point
      {
          public readonly int X { get; }
          public readonly int Y { get; }
      
          public Point(int x, int y)
          {
              X = x;
              Y = y;
          }
      }
      
      Point p1 = new Point(10, 20);
      p1.X = 30;  // ❌ Compilation error: cannot modify readonly property
      
    • Immutable structs are useful for ensuring data integrity and thread safety.

Why Does Mutability Matter?

Common Pitfalls When Choosing

  1. Overusing Classes for Small Data:
    If a class is used for small, frequently created objects, it can lead to excessive garbage collection, slowing down the application.

  2. Using Large Structs:
    Structs should remain small; using large structs can lead to excessive memory copying and performance degradation.

  3. Ignoring Value vs Reference Semantics:
    Accidentally treating structs like classes can result in unexpected behavior, such as failing to update values correctly.