C# Structs
A struct (short for structure) is a value type that groups related data together — similar to a class, but with key differences in how it is stored and copied in memory. Structs are best used for small, simple data containers.
Struct vs Class
┌────────────────────────────────┬────────────────────────────────┐ │ Class │ Struct │ ├────────────────────────────────┼────────────────────────────────┤ │ Reference type │ Value type │ ├────────────────────────────────┼────────────────────────────────┤ │ Stored on the heap │ Stored on the stack │ ├────────────────────────────────┼────────────────────────────────┤ │ Assigned = both point to same │ Assigned = full copy made │ │ object (shared reference) │ (independent copy) │ ├────────────────────────────────┼────────────────────────────────┤ │ Can be null │ Cannot be null (normally) │ ├────────────────────────────────┼────────────────────────────────┤ │ Supports inheritance │ Cannot be inherited │ ├────────────────────────────────┼────────────────────────────────┤ │ Best for complex objects │ Best for small data bundles │ └────────────────────────────────┴────────────────────────────────┘
Defining a Struct
Use the struct keyword. Struct syntax looks almost identical to class syntax.
struct Point
{
public int X;
public int Y;
}
struct Color
{
public byte R;
public byte G;
public byte B;
}
Creating and Using Struct Instances
struct Point
{
public int X;
public int Y;
}
class Program
{
static void Main()
{
Point p;
p.X = 10;
p.Y = 20;
Console.WriteLine("X=" + p.X + ", Y=" + p.Y); // X=10, Y=20
// Or using new:
Point origin = new Point(); // X=0, Y=0 (default values)
Console.WriteLine(origin.X); // 0
}
}
Struct with Constructor and Methods
struct Rectangle
{
public double Width;
public double Height;
public Rectangle(double width, double height)
{
Width = width;
Height = height;
}
public double Area()
{
return Width * Height;
}
public double Perimeter()
{
return 2 * (Width + Height);
}
public void Display()
{
Console.WriteLine($"Rectangle {Width}x{Height}");
Console.WriteLine($"Area: {Area()}, Perimeter: {Perimeter()}");
}
}
class Program
{
static void Main()
{
Rectangle r = new Rectangle(5, 3);
r.Display();
// Rectangle 5x3
// Area: 15, Perimeter: 16
}
}
Value Type Behavior — Copy on Assign
Assigning one struct to another creates a complete, independent copy. Changes to the copy do not affect the original.
struct Point
{
public int X;
public int Y;
}
Point a = new Point();
a.X = 5;
a.Y = 10;
Point b = a; // b gets a COPY of a
b.X = 99; // modify b
Console.WriteLine(a.X); // 5 — a is unchanged
Console.WriteLine(b.X); // 99 — b is separate
Copy Behavior Diagram
┌──────────────────────────────────────────────────────────────┐
│ STRUCT (value type) — copy on assign │
├──────────────────────────────────────────────────────────────┤
│ │
│ Point a = { X=5, Y=10 } │
│ │ │
│ ▼ b = a (full copy made) │
│ Point b = { X=5, Y=10 } ← independent copy │
│ │
│ b.X = 99 │
│ b → { X=99, Y=10 } │
│ a → { X=5, Y=10 } ← a unchanged │
│ │
├──────────────────────────────────────────────────────────────┤
│ CLASS (reference type) — shared reference │
├──────────────────────────────────────────────────────────────┤
│ │
│ Car a = new Car() { Model="X" } │
│ Car b = a; ← b points to SAME object as a │
│ b.Model = "Y"; │
│ a.Model → "Y" ← a also changed! │
│ │
└──────────────────────────────────────────────────────────────┘
Struct Restrictions
┌────────────────────────────────────────────────────────────┐ │ Struct Limitations: │ │ ❌ Cannot inherit from another struct or class │ │ ❌ Cannot be a base class │ │ ❌ Cannot have a parameterless constructor (before C# 10) │ │ ❌ Cannot have field initializers (before C# 10) │ │ ✅ Can implement interfaces │ │ ✅ Can have constructors with parameters │ │ ✅ Can have methods, properties, indexers │ └────────────────────────────────────────────────────────────┘
Struct with Properties
struct Temperature
{
private double _celsius;
public double Celsius
{
get { return _celsius; }
set { _celsius = value; }
}
public double Fahrenheit
{
get { return _celsius * 9 / 5 + 32; }
}
public Temperature(double celsius)
{
_celsius = celsius;
}
}
class Program
{
static void Main()
{
Temperature t = new Temperature(100);
Console.WriteLine(t.Celsius); // 100
Console.WriteLine(t.Fahrenheit); // 212
}
}
Real-World Uses of Struct
┌────────────────────────────────────────────────────────────┐ │ Common struct uses in C# and .NET: │ ├────────────────────────────────────────────────────────────┤ │ Point → X and Y coordinates │ │ Color → R, G, B, A values │ │ DateTime → date and time data │ │ Guid → unique identifier │ │ decimal → financial precision number │ │ int, double, bool → these are all structs in .NET! │ └────────────────────────────────────────────────────────────┘
When to Use Struct vs Class
Use STRUCT when: ✅ Data is small (2–4 fields) ✅ The data is logically a single value (like a coordinate) ✅ Instances are short-lived and frequently created ✅ You want copy-on-assign behavior (immutable-ish data) ✅ No need for inheritance Use CLASS when: ✅ Data is complex with many fields ✅ You need inheritance or polymorphism ✅ Objects have identity (same object shared in multiple places) ✅ The type needs to support null ✅ Object lifetimes are long or managed by garbage collector
Quick Summary
┌─────────────────────────────────────────────────────────────┐ │ struct keyword → defines a value type │ │ Stack-allocated → faster creation and cleanup │ │ Copied on assign → changes to copy don't affect original │ │ Cannot inherit → no class hierarchy │ │ Can have: → fields, constructors, methods, props │ │ Best for: → small data like coordinates, colors │ └─────────────────────────────────────────────────────────────┘
Structs are a lean, efficient way to bundle related values together. Every primitive type in C# — int, double, bool — is actually a struct under the hood. Knowing when to choose struct over class is a sign of a developer who thinks about both correctness and performance.
