Condividi tramite


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

Scelta tra classi e strutture

Altre risorse

Linee guida di progettazione dei tipi

Linee guida di progettazione per lo sviluppo di librerie di classi