Conception de structures
Les structures sont des types valeur. Elles sont allouées sur la pile ou inline et libérées lorsqu'elles sont hors de portée. En général, les types valeur sont plus faciles à allouer et à libérer ; toutefois, s'ils sont utilisés dans des scénarios exigeant un grand nombre d'opérations de boxing et d'unboxing, ils sont nettement moins intéressants en termes de performances que les types référence. Pour plus d'informations, consultez Boxing et unboxing (Guide de programmation C#).
Pour plus d'informations sur les types valeur et les types référence, consultez Système de type commun.
Ne fournissez pas de constructeur par défaut pour une structure.
Si une structure définit un constructeur par défaut, lors de la création des tableaux de la structure, le Common Language Runtime exécute automatiquement le constructeur par défaut sur chaque élément de tableau.
Certains compilateurs, tels que le compilateur C#, ne permettent pas aux structures d'avoir des constructeurs par défaut.
Implémentez System.IEquatable`1 sur les types valeur.
Pour déterminer si deux types valeur sont égaux, il est préférable d'utiliser IEquatable<T> au lieu de Equals. En utilisant l'interface, l'appelant évite la diminution des performances liée à l'utilisation du boxing et de la réflexion managée.
Assurez-vous qu'un état où toutes les données d'instance ont la valeur zéro, false, ou null (selon les cas) est valide.
En respectant cette consigne, vous évitez que les nouvelles instances de type valeur construites soient inutilisables. Par exemple, la conception de la structure suivante est incorrecte : le constructeur paramétré est censé garantir un état valide, mais il n'est pas exécuté lors de la création d'un tableau de la structure. Cela signifie que le champ d'instance label est initialisé avec la valeur null (Nothing en Visual Basic), qui n'est pas valide pour l'implémentation de ToString de cette structure.
Public Structure BadStructure
Private label As String
Private width As Integer
Private length As Integer
Public Sub New(ByVal labelValue As String, ByVal widthValue As Integer, ByVal lengthValue As Integer)
If ((labelValue = Nothing) _
OrElse (labelValue.Length = 0)) Then
Throw New ArgumentNullException("label")
End If
label = labelValue
width = widthValue
length = lengthValue
End Sub
Public Overrides Function ToString() As String
' Accessing label.Length throws a NullReferenceException
' when label is null.
Return String.Format("Label length: {0} Label: {1} Width: {2} Length: {3}", label.Length, label, width, length)
End Function
End Structure
public struct BadStructure
{
string label;
int width;
int length;
public BadStructure (string labelValue, int widthValue, int lengthValue)
{
if (labelValue == null || labelValue.Length ==0)
{
throw new ArgumentNullException("label");
}
label = labelValue;
width = widthValue;
length = lengthValue;
}
public override string ToString()
{
// Accessing label.Length throws a NullReferenceException
// when label is null.
return String.Format("Label length: {0} Label: {1} Width: {2} Length: {3}",
label.Length, label, width,length);
}
}
Dans l'exemple de code suivant, la conception de GoodStructure ne présuppose rien quant à l'état du champ label. La méthode ToString est conçue pour gérer une étiquette null.
Public Structure GoodStructure
Private label As String
Private width As Integer
Private length As Integer
Public Sub New(ByVal labelValue As String, ByVal widthValue As Integer, ByVal lengthValue As Integer)
label = labelValue
width = widthValue
length = lengthValue
End Sub
Public Overrides Function ToString() As String
' Handle the case where label might be
' initialized to null;
Dim formattedLabel As String = label
Dim formattedLableLength As Integer
If (formattedLabel = Nothing) Then
formattedLabel = "<no label value specified>"
formattedLableLength = 0
Else
formattedLableLength = label.Length
End If
Return String.Format("Label Length: {0} Label: {1} Width: {2} Length: {3}", formattedLableLength, formattedLabel, width, length)
End Function
End Structure
public struct GoodStructure
{
string label;
int width;
int length;
public GoodStructure (string labelValue, int widthValue, int lengthValue)
{
label = labelValue;
width = widthValue;
length = lengthValue;
}
public override string ToString()
{
// Handle the case where label might be
// initialized to null;
string formattedLabel = label;
int formattedLableLength;
if (formattedLabel == null)
{
formattedLabel = "<no label value specified>";
formattedLableLength = 0;
} else
{
formattedLableLength = label.Length;
}
return String.Format("Label Length: {0} Label: {1} Width: {2} Length: {3}",
formattedLableLength, formattedLabel, width, length);
}
}
N'étendez pas explicitement System.ValueType.
Certains compilateurs ne permettent pas d'étendre ValueType.
Portions Copyright 2005 Microsoft Corporation. Tous droits réservés.
Portions Copyright Addison-Wesley Corporation. Tous droits réservés.
Pour plus d'informations sur les règles de conception, consultez « règles de conception d'infrastructure : Conventions idiomes et modèles carnet de bibliothèques réutilisables framework » Krzysztof Cwalina et Brad Abrams, publiés par Addison-Wesley, 2005.
Voir aussi
Concepts
Choix entre des classes et des structures
Autres ressources
Instructions de conception de types
Instructions de conception pour le développement de bibliothèques de classes