Didacticiel sur les structures
Ce didacticiel présente la syntaxe et l'utilisation des structures. Il couvre également les principales différences entre les classes et les structures.
Fichiers d'exemple
Pour télécharger et construire les exemples de fichier proposés dans ce didacticiel, consultez Structures, exemple.
Sources d'informations supplémentaires
- struct
- 1.8 Structs
- Syntaxe des structs dans C. Grammaire
- Types valeur
- Attributs du C#
- 17. Attributs
- StructLayoutAttribute
Didacticiel
Ce didacticiel inclut deux exemples. Le premier montre comment déclarer et utiliser les structures, le second présente la différence entre les structures et les classes lorsque les instances sont transmises aux méthodes. Les sujets suivants sont également abordés :
- Structures et classes
- Tas ou pile ?
- Constructeurs et héritage
- Attributs sur les structures
Exemple 1
Cet exemple déclare une structure avec trois membres : une propriété, une méthode et un champ privé. Il crée et utilise une instance de la structure :
// struct1.cs
using System;
struct SimpleStruct
{
private int xval;
public int X
{
get
{
return xval;
}
set
{
if (value < 100)
xval = value;
}
}
public void DisplayX()
{
Console.WriteLine("The stored value is: {0}", xval);
}
}
class TestClass
{
public static void Main()
{
SimpleStruct ss = new SimpleStruct();
ss.X = 5;
ss.DisplayX();
}
}
Résultat
The stored value is: 5
Structures et classes
Les structures peuvent sembler très similaires aux classes, mais il existe des différences importantes dont vous devez avoir conscience. Tout d'abord, les classes sont des types référence et les structures des types valeur. Avec des structures, vous pouvez créer des objets qui se comportent comme les types intégrés et bénéficient également de leurs avantages.
Tas ou pile ?
Lorsque vous appelez l'opérateur New sur une classe, il est alloué sur le segment. Mais lorsque vous instanciez une structure, elle est créée sur la pile. Cela aboutit à de meilleures performances. Par ailleurs, vous ne traitez pas les références à une instance d'une structure comme des classes. Vous travaillez directement sur l'instance de structure. C'est pourquoi, lorsque vous transmettez une structure à une méthode, elle est transmise par valeur, et non en tant que référence.
Exemple 2
Cet exemple montre que si vous transmettez une structure à une méthode, vous transmettez en fait une copie de la structure, mais que si vous transmettez une instance de classe, vous transmettez une référence.
// struct2.cs
using System;
class TheClass
{
public int x;
}
struct TheStruct
{
public int x;
}
class TestClass
{
public static void structtaker(TheStruct s)
{
s.x = 5;
}
public static void classtaker(TheClass c)
{
c.x = 5;
}
public static void Main()
{
TheStruct a = new TheStruct();
TheClass b = new TheClass();
a.x = 1;
b.x = 1;
structtaker(a);
classtaker(b);
Console.WriteLine("a.x = {0}", a.x);
Console.WriteLine("b.x = {0}", b.x);
}
}
Résultat
a.x = 1 b.x = 5
Description du code
Le résultat obtenu avec l'exemple de code montre que seule la valeur du premier champ de classe a changé lorsque l'instance de classe a été transmise à la méthode classtaker. Le champ de structure, lui, n'a pas changé lors de la transmission de son instance à la méthode structtaker. Cela s'explique de la façon suivante : une copie de la structure a été transmise à la méthode structtaker, tandis qu'une référence à la classe a été transmise à la méthode classtaker.
Constructeurs et héritage
Les structures peuvent déclarer des constructeurs, mais elles doivent prendre des paramètres. Déclarer un constructeur par défaut (sans paramètre) pour une structure constitue une erreur. Les membres d'une structure ne peuvent pas avoir d'initialiseurs. Un constructeur par défaut est toujours fourni pour initialiser les membres de la structure à leurs valeurs par défaut respectives.
Lorsque vous employez l'opérateur New pour créer un objet struct, celui-ci est créé et le constructeur approprié est appelé. Contrairement aux classes, les objets struct peuvent être instanciés sans recours à l'opérateur New. Si vous n'utilisez pas cet opérateur, les champs ne seront pas assignés et l'objet ne pourra pas être utilisé tant que tous les champs n'auront pas été initialisés.
Il n'existe pas d'héritage pour les structures comme il en existe pour les classes. Un struct ne peut pas hériter d'un autre struct ou d'une classe ; il ne peut pas non plus servir de base à une classe. Toutefois, les structures héritent de l'objet classe de base. Un struct peut implémenter des interfaces exactement de la même manière que les classes. Voici un extrait de code d'un struct implémentant une interface :
interface IImage
{
void Paint();
}
struct Picture : IImage
{
public void Paint()
{
// painting code goes here
}
private int x, y, z; // other struct members
}
Attributs sur les structures
L'utilisation d'attributs vous permet de personnaliser la présentation des structures dans la mémoire. Par exemple, vous pouvez créer ce qu'on appelle une union en C/C++ avec les attributs StructLayout(LayoutKind.Explicit) et FieldOffset.
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Explicit)]
struct TestUnion
{
[FieldOffset(0)]
public int i;
[FieldOffset(0)]
public double d;
[FieldOffset(0)]
public char c;
[FieldOffset(0)]
public byte b1;
}
Dans le segment de code précédent, tous les champs de TestUnion commencent au même emplacement dans la mémoire.
Le code suivant est un autre exemple dans lequel les champs commencent à des emplacements différents définis de manière explicite :
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Explicit)]
struct TestExplicit
{
[FieldOffset(0)]
public long lg;
[FieldOffset(0)]
public int i1;
[FieldOffset(4)]
public int i2;
[FieldOffset(8)]
public double d;
[FieldOffset(12)]
public char c;
[FieldOffset(14)]
public byte b1;
}
Les deux champs int, i1 et i2, partagent les mêmes emplacements de la mémoire que lg. Ce type de contrôle sur la disposition d'une structure est utile lorsque vous utilisez l'appel de plate-forme.
Conclusion
La manipulation des structures est aisée et celles-ci peuvent parfois se révéler utiles. Souvenez-vous simplement qu'elles sont créées sur la pile et que vous traitez non pas des références aux structures, mais les structures proprement dites. Si vous avez besoin d'un type qui sera souvent utilisé et qui est essentiellement une simple donnée, les structures peuvent être une option intéressante.