Freigeben über


Strukturentwurf

Aktualisiert: November 2007

Strukturen sind Werttypen. Sie werden auf dem Stapel oder inline reserviert und freigegeben, wenn sie den Gültigkeitsbereich verlassen. Im Allgemeinen können Werttypen mit weniger Aufwand reserviert und freigegeben werden. Wenn sie jedoch in Szenarien verwendet werden, in denen Boxing und Unboxing in wesentlichem Umfang erfolgt, ist ihre Leistung im Vergleich zu Verweistypen gering. Weitere Informationen finden Sie unter Boxing und Unboxing (C#-Programmierhandbuch).

Weitere Informationen über Werttypen und Verweistypen finden Sie unter Übersicht über das allgemeine Typsystem.

Stellen Sie für eine Struktur keinen Standardkonstruktor bereit.

Wenn eine Struktur beim Erstellen von Arrays der Struktur einen Standardkonstruktor definiert, führt die Common Language Runtime automatisch den Standardkonstruktor für jedes Arrayelement aus.

Einige Compiler, z. B. der C#-Compiler, lassen Standardkonstruktoren für Strukturen nicht zu.

Implementieren Sie für Werttypen System.IEquatable'1.

Um zu bestimmen, ob zwei Werttypen gleich sind, ist IEquatable<T> besser geeignet als Equals. Durch die Verwendung der Schnittstelle vermeidet der Aufrufer die negativen Auswirkungen von Boxing und verwalteter Reflektion auf die Leistung.

Stellen Sie sicher, dass ein Zustand, in dem alle Instanzdaten auf 0 (null), false bzw. NULL festgelegt sind, gültig ist.

Durch Befolgen dieser Richtlinie bleiben die neu erstellten Werttypinstanzen nicht in einem unbrauchbaren Zustand. Beispielsweise wurde die folgende Struktur falsch entworfen. Der parametrisierte Konstruktor soll einen gültigen Zustand sicherstellen, doch der Konstruktor wird nicht ausgeführt, wenn ein Array der Struktur erstellt wird. Daher wird das Instanzfeld label mit null (Nothing in Visual Basic) initialisiert. Dies ist für die Implementierung von ToString dieser Struktur nicht gültig.

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);
    }
}

Im folgenden Codebeispiel erfolgt der Entwurf von GoodStructure ohne Prämissen über den Zustand des label-Felds. Der Zweck der ToString-Methode ist die Behandlung einer null-Bezeichnung.

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);
    }
}

Erweitern Sie System.ValueType nicht explizit.

Einige Compiler lassen das Erweitern von ValueType nicht zu.

Copyright für einzelne Teile 2005 Microsoft Corporation. Alle Rechte vorbehalten.

Copyright für einzelne Teile Addison-Wesley Corporation. Alle Rechte vorbehalten.

Weitere Informationen zu Entwurfsrichtlinien finden Sie im Buch "Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries" von Krzysztof Cwalina und Brad Abrams, veröffentlicht von Addison-Wesley, 2005.

Siehe auch

Konzepte

Auswählen zwischen Klassen und Strukturen

Weitere Ressourcen

Richtlinien für den Entwurf von Typen

Entwurfsrichtlinien zum Entwickeln von Klassenbibliotheken