Progettazione di strutture
Le strutture sono tipi di valore. Vengono allocate nello stack o inline e disallocate quando non rientrano più nell'ambito di validità. In generale, i tipi di valore sono più convenienti da allocare e disallocare, a meno che non vengano utilizzati in scenari che richiedono numerose operazioni di boxing e unboxing. In tal caso, infatti, le prestazioni risultano inferiori rispetto a quelle dei tipi di riferimento. Per ulteriori informazioni, vedere Boxing and Unboxing (C# Programming Guide).
Per ulteriori informazioni sui tipi di valore e i tipi di riferimento, vedere Common Type System.
Non fornire un costruttore predefinito per una struttura.
Se una struttura definisce un costruttore predefinito, quando vengono create le matrici della struttura Common Language Runtime esegue automaticamente il costruttore predefinito su ciascun elemento della matrice.
Alcuni compilatori, quali C#, non consentono costruttori predefiniti per le strutture.
Nei tipi di valore implementare System.IEquatable`1.
Per determinare se due tipi di valore sono uguali, è preferibile utilizzare IEquatable<T> anziché Equals. Utilizzando l'interfaccia il chiamante evita l'impatto negativo sulle prestazioni dovuto alle operazioni di boxing e alla reflection gestita.
Assicurarsi che uno stato in cui tutti i dati di istanza sono impostati su zero, false o null (a seconda dei casi) sia valido.
Se si osserva questa indicazione, le nuove istanze di tipi di valore costruite non verranno lasciate in uno stato di non utilizzo. La struttura riportata di seguito, ad esempio, non è progettata correttamente. Il costruttore con parametri deve garantire uno stato valido, ma non viene eseguito quando viene creata una matrice della struttura. Ciò significa che il campo label dell'istanza viene inizializzato su null (Nothing in Visual Basic), un valore non valido per l'implementazione di ToString in questa struttura.
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);
}
}
Nell'esempio di codice riportato di seguito la progettazione di GoodStructure non ipotizza alcuno stato del campo label. Il metodo ToString viene utilizzato per gestire un'etichetta 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);
}
}
Non estendere System.ValueType in modo esplicito.
Alcuni compilatori non consentono di estendere ValueType.
Portions Copyright 2005 Microsoft Corporation. Tutti i diritti riservati.
Portions Copyright Addison-Wesley Corporation. Tutti i diritti riservati.
Per ulteriori informazioni sulle linee guida di progettazione, vedere “le linee guida di progettazione di Framework: Idiomi convenzioni, e modelli per libro raccolte riutilizzabili .NET„ di Krzysztof Cwalina e brad Abrams, emessi da Addison-Wesley, 2005.
Vedere anche
Concetti
Altre risorse
Linee guida di progettazione dei tipi
Linee guida di progettazione per lo sviluppo di librerie di classi