Share via


構造体のデザイン

構造体は値型です。 構造体は、スタックまたはインラインに割り当てられ、スコープの外に出たときに解放されます。 通常、値型は割り当ておよび解放するのにより小さな負荷で済みますが、大量のボックス化およびボックス化解除が必要なシナリオで使用した場合は、参照型に比べてパフォーマンスが劣ります。 詳細については、「ボックス化とボックス化解除 (C# プログラミング ガイド)」を参照してください。

値型と参照型の詳細については、「共通型システム」を参照してください。

構造体には、既定のコンストラクターを提供しないでください。

構造体で既定のコンストラクターを定義した場合、構造体の配列の作成時に共通言語ランタイムは、各配列要素で既定のコンストラクターを自動的に実行します。

C# コンパイラなどの一部のコンパイラでは、構造体で既定のコンストラクターを使用できません。

値型には System.IEquatable`1 を実装してください。

2 つの値型が等しいかどうかを判別するには、Equals よりも IEquatable<T> をお勧めします。 呼び出し元は、インターフェイスを使用して、ボックス化やマネージ リフレクションによるパフォーマンスへの影響を回避します。

すべてのインスタンス データが必要に応じて、ゼロ、false、または null に設定される状態が有効であることを確認してください。

このガイドラインに従って新たに構築された値型インスタンスが使用不能な状態になることはありません。 デザインに問題がある構造体の例を次に示します。 このパラメーター付きのコンストラクターは、有効な状態を確保するものとして用意されていますが、構造体の配列の作成時に実行されません。 そのため、インスタンス フィールド label は null (Visual Basic の場合は Nothing) に初期化され、この構造体の ToString の実装に対して無効になります。

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

次のコード例の GoodStructure のデザインは、label フィールドの状態について想定しません。 ToString は、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);
    }
}

System.ValueType を明示的に拡張しないでください。

一部のコンパイラでは、ValueType を拡張できません。

Portions Copyright 2005 Microsoft Corporation. All rights reserved.

Portions Copyright Addison-Wesley Corporation. All rights reserved.

設計ガイドラインの詳細についてを参照してください、「フレームワークの設計ガイドライン。規則、慣用句、および再利用可能なパターン。ネット ライブラリ」本クシシュトフ Cwalina、ブラッド エイブラムス、アスキー、2005 年発表しました。

参照

概念

クラスまたは構造体の選択

その他の技術情報

型のデザインのガイドライン

クラス ライブラリ開発のデザイン ガイドライン