1. Intro
A structure is a special data type in C# that lets you combine several values (even of different types) into one "box." It's kinda like a small LEGO set: you put the pieces together and get a handy, compact object.
Structs are similar to classes, but they've got their own quirks, and they're used for more "simple" cases where you don't need all the power and "heaviness" of classes.
Syntax
struct Point
{
public int X;
public int Y;
}
In this example, we described a struct for a point on a plane with coordinates X and Y.
Where are structs used?
Most often, structs are used for small, simple objects that should be super lightweight and "just data."
In C#, some standard types are structs:
- int, double, bool, DateTime, TimeSpan, decimal, Guid
- and even, for example, ConsoleKeyInfo or Point (in graphics libraries)
Differences between structs and classes
| Criterion | Struct | Class |
|---|---|---|
| Keyword | |
|
| Storage type | Value Type | Reference Type |
| Stored in | Stack (memory area) | Heap (memory area) |
| Passing to method | By value (copy) | By reference |
| Inheritance | No (except interfaces) | Yes |
| Can be null | No (only Nullable) | Yes |
| By default | Implicitly initializes all fields to zero | Only via constructor |
2. Declaring and using structs
You can declare a struct inside or outside a class:
struct Rectangle
{
public int Width;
public int Height;
}
Creating and using:
Rectangle r;
r.Width = 10;
r.Height = 5;
Console.WriteLine($"Area: {r.Width * r.Height}");
You can also use a constructor:
struct Point
{
public int X;
public int Y;
// Constructor
public Point(int x, int y)
{
X = x;
Y = y;
}
}
var p = new Point(3, 7);
Console.WriteLine($"Point: ({p.X}, {p.Y})");
When is it better to use a struct?
- For small "bundles" of data (like coordinate, color, range, date and time).
- When compactness and performance matter (like millions of points in an array).
- When the object should behave like a single value (copy-paste — it's really a copy!).
You shouldn't use a struct if the object:
- Can be big (lots of fields).
- Needs to be part of an inheritance hierarchy.
- Needs to be changed often by reference.
3. Struct quirks and "gotchas"
Copying
Point p1 = new Point(1, 2);
Point p2 = p1; // a COPY is created!
p2.X = 100;
Console.WriteLine(p1.X); // 1 — didn't change!
Console.WriteLine(p2.X); // 100
Implicit default values
Point p; // fields X and Y = 0, even if you didn't assign them!
Can be Nullable
To store null, you need to use special nullable syntax — put a question mark after the type name. Then you can assign null to the variable.
Point? p = null;
if (p == null)
Console.WriteLine("No point");
4. Structs with auto-properties and methods
Structs can have methods, properties, events, and even static members.
public struct Range
{
public int Start { get; set; }
public int End { get; set; }
public int Length => End - Start;
public override string ToString() => $"[{Start}..{End}]";
}
Example: struct for complex numbers
Struct for complex numbers with a method and override of ToString()
struct Complex
{
public double Re;
public double Im;
public Complex(double re, double im)
{
Re = re;
Im = im;
}
public double Abs() => Math.Sqrt(Re * Re + Im * Im);
public override string ToString() => $"{Re} + {Im}i";
}
var z = new Complex(1, 2);
Console.WriteLine(z); // 1 + 2i
Console.WriteLine(z.Abs()); // 2.236...
GO TO FULL VERSION