C# : Les structs
Value types personnalisés, différences avec les classes, quand utiliser un struct - les types valeur en C#.
C# : Les structs
En C#, class crée un type référence (stocké sur le heap). Mais parfois, tu veux un type simple, léger, qui se comporte comme un int - stocké sur la stack, copié par valeur. C'est le rôle du struct.
Si tu n'as pas encore lu l'article sur la mémoire, fais-le d'abord - la distinction stack/heap est essentielle ici.
# Déclaration
Un struct se déclare comme une classe, avec struct à la place de class :
struct Point
{
public double X { get; }
public double Y { get; }
public Point(double x, double y)
{
X = x;
Y = y;
}
public double DistanceTo(Point other)
{
double dx = X - other.X;
double dy = Y - other.Y;
return Math.Sqrt(dx * dx + dy * dy);
}
}struct Point{ public double X { get; } public double Y { get; } public Point(double x, double y) { X = x; Y = y; } public double DistanceTo(Point other) { double dx = X - other.X; double dy = Y - other.Y; return Math.Sqrt(dx * dx + dy * dy); }}Utilisation identique à une classe :
Point a = new Point(0, 0);
Point b = new Point(3, 4);
Console.WriteLine(a.DistanceTo(b)); // 5Point a = new Point(0, 0);Point b = new Point(3, 4);Console.WriteLine(a.DistanceTo(b)); // 5# Comportement par valeur
C'est la différence fondamentale. Un struct est copié par valeur - modifier la copie ne touche pas l'original :
Point a = new Point(1, 2);
Point b = a; // copie complète de toutes les données
// b est totalement indépendant de aPoint a = new Point(1, 2);Point b = a; // copie complète de toutes les données // b est totalement indépendant de aAvec une classe, b = a copierait la référence - les deux variables pointeraient vers le même objet. Avec un struct, chaque variable a sa propre copie des données.
# Struct vs classe
| Struct | Classe | |
|---|---|---|
| Type | Value type (stack) | Reference type (heap) |
| Copie | Par valeur (copie complète) | Par référence (même objet) |
| Héritage | Non (ne peut pas hériter ni être hérité) | Oui |
| Interfaces | Oui | Oui |
| Valeur par défaut | Tous les champs à 0/null/false | null |
new obligatoire | Non (peut utiliser la valeur par défaut) | Oui |
| Performance | Rapide pour les petits types | Allocation heap + GC |
# Quand utiliser un struct
Un struct est le bon choix quand :
- L'objet est petit (typiquement < 16 octets - quelques
int,double,bool) - L'objet est éphémère (créé souvent, utilisé brièvement)
- L'objet représente une valeur unique (un point, une couleur, une date, un montant)
- Tu veux une sémantique de copie (chaque variable a sa propre valeur)
Les exemples classiques du framework .NET : int, double, bool, DateTime, TimeSpan, Guid - ce sont tous des structs.
Ne crée pas un struct pour un objet complexe avec beaucoup de champs. Chaque passage à une méthode copie toutes les données. Un struct de 200 octets passé 100 fois = 20 Ko copiés pour rien. Utilise une classe ou le mot-clé in (voir passage de paramètres).
# Readonly struct (C# 7.2+)
Un readonly struct garantit que tous les champs sont en lecture seule. Le compilateur vérifie qu'aucune méthode du struct ne modifie l'état.
readonly struct Point
{
public double X { get; }
public double Y { get; }
public Point(double x, double y)
{
X = x;
Y = y;
}
}readonly struct Point{ public double X { get; } public double Y { get; } public Point(double x, double y) { X = x; Y = y; }}C'est une bonne pratique par défaut - la plupart des structs devraient être readonly. Ça permet aussi au compilateur d'optimiser les passages in sans copie défensive.
# La suite
- Les records - immutabilité et comparaison par valeur
- Les enums - énumérations et constantes nommées