Struct ou Class en C# : le débat éternel des débutants et des pros
\n\nAvez-vous déjà réfléchi à pourquoi il existe en C# deux façons très similaires de créer votre propre type de données — class et struct ? Et pourquoi sur Stack Overflow la question « When should I use a struct rather than a class in C#? » recueille des milliers de vues et des centaines de réponses ? Le fait est que derrière une apparente simplicité se cache une nuance profonde qui peut soit accélérer votre programme, soit le transformer en nid à bugs.
Dans cet article, nous allons analyser en quoi struct diffère de class, quand utiliser struct, et quand il vaut mieux oublier son existence. Sans termes compliqués, avec des exemples concrets et des conseils pratiques. C'est parti !
\n\nLa principale différence : pile ou tas ?
\n\nLe point le plus important à comprendre est la distinction entre types de valeur (value types) et types de référence (reference types).
\n\n- \n
- Class — type de référence. L'objet est stocké dans le tas (heap) géré, et la variable ne contient qu'une référence (adresse) vers cet objet. \n
- Struct — type de valeur (value type). La variable stocke directement les données dans la pile (stack) ou à l'intérieur d'un autre objet. \n
Cela semble abstrait ? Prenons un exemple. Imaginez que les données sont un livre. Class est le titre du livre et le numéro de l'étagère où il se trouve dans la bibliothèque. Struct est le livre lui-même que vous portez dans votre poche. Lorsque vous passez un class à une méthode, vous transmettez le numéro de l'étagère. Lorsque vous passez un struct, vous donnez une copie du livre.
\n\nExemple de code : class vs struct
\n\npublic class PointClass\n{\n public int X { get; set; }\n public int Y { get; set; }\n\n public PointClass(int x, int y)\n {\n X = x;\n Y = y;\n }\n}\n\npublic struct PointStruct\n{\n public int X { get; set; }\n public int Y { get; set; }\n\n public PointStruct(int x, int y)\n {\n X = x;\n Y = y;\n }\n}\n\n// Utilisation\nvar pointClass = new PointClass(10, 20);\nvar pointStruct = new PointStruct(10, 20);\n\n// Passage à une méthode\nvoid ModifyPointClass(PointClass p) { p.X = 100; }\nvoid ModifyPointStruct(PointStruct p) { p.X = 100; }\n\nModifyPointClass(pointClass); // pointClass.X devient 100\nModifyPointStruct(pointStruct); // pointStruct.X reste 10 — copie !\n\n\nVous voyez ? Struct est copié lors du passage. C'est la différence clé qui détermine quand l'utiliser.
\n\nQuand struct est votre ami : 3 cas en béton
\n\nMicrosoft recommande d'utiliser struct si votre type de données satisfait TOUTES les conditions suivantes :
1. Les données sont petites et simples
\nStruct est idéal pour de petits ensembles de données (recommandé pas plus de 16-24 octets). Par exemple, un point, une couleur, un vecteur, un nombre complexe, des coordonnées.
\n\npublic struct RgbColor\n{\n public byte R { get; }\n public byte G { get; }\n public byte B { get; }\n\n public RgbColor(byte r, byte g, byte b)\n {\n R = r;\n G = g;\n B = b;\n }\n}\n\n\nPourquoi ? Parce que les petits struct se copient rapidement, et le stockage dans la pile réduit la charge sur le ramasse-miettes (GC).
\n\n2. Les objets vivent peu de temps et ne changent pas
\nSi vos données sont des valeurs immuables (immutable), struct est un excellent choix. Par exemple, des coordonnées sur une carte : vous ne modifiez pas un point, vous en créez un nouveau.
\n\npublic struct GeoLocation\n{\n public double Latitude { get; }\n public double Longitude { get; }\n\n public GeoLocation(double lat, double lon)\n {\n Latitude = lat;\n Longitude = lon;\n }\n\n public GeoLocation MoveNorth(double meters)\n {\n // Retourne une nouvelle instance, ne modifie pas l'ancienne\n return new GeoLocation(Latitude + meters / 111111.0, Longitude);\n }\n}\n\n\n