Struct in C#
Differences between struct in C++ and C#, and Unity Vector2 case study
Struct: Differences in C++ vs C#, and Unity Vector2 Case Study
Introduction
In Unity development, I’ve seen C++ programmers use struct the way they used to in C++ out of habit. For example, I’ve seen cases where large data like player is made into struct and used in collections like Queue or Dictionary.
At that time, experiencing performance issues and unexpected behaviors, I want to summarize how struct differs between C++ and C#, and how Unity handles structs like Vector2.
C++ Struct vs C# Struct
| Aspect | C++ Struct | C# Struct |
|---|---|---|
| Basic Meaning | Almost identical to class | Value Type |
| Inheritance | Possible | Not possible (only interface implementation) |
| Memory Location | Heap or Stack | Stack (or inline) |
| Default Constructor | Compiler generated | Must be explicitly defined |
| Destructor | Can be auto-called | Cannot be explicitly defined |
Key Differences in Detail
1. Memory Management
C++: struct instances are allocated on stack or heap depending on declaration location.
C#: structs are always allocated on stack (except when containing reference types). Large structs can cause stack overflow.
2. Copy Behavior
C++: Can pass efficiently via pointers or references.
C#: Every time you pass a struct to a function or assign to a variable, a full copy occurs.
struct Point
{
public int X, Y;
}
void ModifyPoint(Point p)
{
p.X = 10; // Doesn't affect original (modifying copy)
}
// Solution: use ref
void ModifyPoint(ref Point p)
{
p.X = 10; // Original is modified
}
3. Collection Usage
C++: Can store struct pointers in collections.
C#: Boxing occurs every time you put a struct in a collection.
List<Point> points = new List<Point>();
points.Add(new Point { X = 1, Y = 2 }); // Copy occurs
Unity Vector2 Case
Unity’s Vector2, Vector3, Quaternion, etc. are all structs.
Vector2 position = transform.position; // Copy occurs
position.x = 5; // transform.position is NOT changed!
// Correct approach
transform.position = new Vector2(5, position.y);
When Should You Use Struct?
✅ Suitable Cases
- Small, immutable data (coordinates, colors, time, etc.)
- Short-lived local variables
- Performance-critical calculation logic
- When you want to reduce GC pressure
❌ Unsuitable Cases
- Large data structures (player, items, level data)
- Frequently changing data
- Objects frequently added/removed from collections
- When inheritance is needed
Performance Tips
- Reduced GC Pressure: Since structs are allocated on stack, not GC heap, garbage collection burden is reduced.
- Array Access Optimization: Struct arrays are contiguously placed in memory for good cache efficiency.
- Copy Cost Caution: Frequently copying large structs can degrade performance.
// Bad example: continuously copying large struct
struct LargeData { public int[] data; } // Array itself is a reference!
// Good example: use class
class LargeData { public int[] data; } // Only reference is copied
Conclusion
For developers coming from C++, it’s easy to misunderstand C# structs as simply “small classes”. However, they clearly have value type semantics, and you should always consider copy behavior and boxing when using them.
The same applies when handling Vector2 in Unity - understanding these characteristics helps avoid unexpected bugs and optimize performance.
🎯 TL;DR: C# structs are suitable for small, immutable data, and should always be used with copy and boxing behavior in mind.