構造体とクラス

更新 : 2007 年 11 月

Visual Basic では、構造体とクラスの構文が統一され、両方のエンティティでほとんど同じ機能がサポートされるようになりました。ただし、構造体とクラスの間には重要な違いもあります。

クラスには、参照型としての利点があります。たとえば、参照型を渡す方が、すべてのデータが格納されている構造体変数を渡すよりも効率的です。一方、構造体の場合は、グローバル ヒープにメモリを割り当てる必要がありません。

構造体からは継承ができないため、構造体は拡張する必要のないオブジェクトにだけ使用することをお勧めします。構造体は、作成するオブジェクトのインスタンスのサイズが小さい場合に使用します。その場合はクラスと構造体の特性の違いを考慮してください。

類似点

構造体とクラスの類似点は次のとおりです。

  • どちらも container 型であり、他の型をメンバとして含みます。

  • どちらにもメンバが含まれます。メンバとしては、コンストラクタ、メソッド、プロパティ、フィールド、定数、列挙値、イベント、およびイベント ハンドラを含むことができます。しかし、これらのメンバと、宣言された構造体の要素とを混同しないでください。

  • どちらのメンバにも、個別のアクセス レベルを設定できます。たとえば、一方のメンバを Public と宣言し、他方のメンバを Private と宣言することができます。

  • どちらもインターフェイスを実装できます。

  • どちらもパラメータ付きまたはパラメータなしの共有コンストラクタを含むことができます。

  • どちらも既定のプロパティを公開できます。ただし、少なくとも 1 つのパラメータを指定する必要があります。

  • どちらもイベントを宣言し発生させて、デリゲートを宣言できます。

異なる点

構造体とクラスの違いは次のとおりです。

  • 構造体は値型、クラスは参照型です。クラス型がデータへの参照を格納するのとは異なり、構造体型の値は構造体のデータそのものを格納します。

  • 構造体はスタック割り当てを使用し、クラスはヒープ割り当てを使用します。

  • 構造体のすべての要素は既定で Public です。クラスでは、変数および定数は既定で Private、他のメンバは既定で Public です。これにより、クラスのメンバは Visual Basic 6.0 の既定値システムとの互換性を持ちます。

  • 構造体には少なくとも 1 つの共有されない変数、または共有されない非カスタムのイベント要素を含む必要がありますが、クラスは完全に空にすることができます。

  • 構造体の要素は、Protected として宣言できませんが、クラス メンバは宣言できます。

  • 構造体のプロシージャは、Shared (Visual Basic)Sub プロシージャである場合にだけ、AddHandler ステートメントを使用してのみイベントを処理できますが、クラスのプロシージャはどれでも、Handles キーワードまたは AddHandler ステートメントを使用してイベントを処理できます。詳細については、「イベントとイベント ハンドラ」を参照してください。

  • 構造体の変数宣言では、初期化子または配列の初期サイズを指定できませんが、クラスの変数宣言では指定できます。

  • 構造体は暗黙に System.ValueType クラスから継承し、それ以外の型からは継承できませんが、クラスは System.ValueType 以外のすべてのクラスから継承できます。

  • 構造体は継承できませんが、クラスは継承できます。

  • 構造体は終了されないため、共通言語ランタイム (CLR: Common Language Runtime) は構造体に対して Finalize メソッドを呼び出しませんが、クラスはガベージ コレクタによって終了され、ガベージ コレクタはアクティブな参照が残っていないことを検出すると、クラスに対して Finalize を呼び出します。

  • 構造体はコンストラクタを必要としませんが、クラスには必要です。

  • 構造体にはパラメータを取る場合にだけ非共有コンストラクタを含むことができますが、クラスにはパラメータの有無には関係なく非共有コンストラクタを含むことができます。

すべての構造体には、パラメータがない暗黙のパブリック コンストラクタが含まれます。このコンストラクタによって、構造体のすべてのデータ要素が既定値に初期化されます。この動作は再定義できません。

インスタンスと変数

構造体は値型であるため、各構造体変数は個別の構造体インスタンスに恒久的に関連付けされます。一方、クラスは参照型であり、オブジェクト変数はさまざまなクラス インスタンスを異なる時点で参照できます。この違いは、構造体とクラスの使用方法に次のように影響します。

  • 初期化 構造体変数には、構造体のパラメータなしコンストラクタを使って、要素の初期化が暗黙的に含まれます。したがって、Dim s As struct1 は Dim s As struct1 = New struct1() に相当します。

  • 変数の割り当て 構造体変数を別の構造体変数に代入するか、または構造体インスタンスをプロシージャ引数に渡すと、すべての変数要素の現在の値が新しい構造体にコピーされます。オブジェクト変数を別のオブジェクト変数に代入するか、またはオブジェクト変数をプロシージャに渡すと、参照ポインタだけがコピーされます。

  • Nothing の割り当て 構造体変数には値 Nothing (Visual Basic) を代入できますが、インスタンスは引き続き変数に関連付けられています。変数要素は代入によって再初期化されますが、以降もその変数のメソッドを呼び出したり、そのデータ要素にアクセスしたりできます。

    一方、オブジェクト変数を Nothing に設定した場合は、クラス インスタンスとの関連付けが解除され、別のインスタンスを代入するまでその変数をとおしてメンバにアクセスすることはできません。

  • 複数のインスタンス オブジェクト変数には異なる時点で異なるクラス インスタンスを代入でき、複数のオブジェクト変数が同時に同じクラス インスタンスを参照できます。クラスのメンバの値に加えた変更は、同じインスタンスを指す別の変数をとおしてアクセスされたときにそのメンバに反映されます。

    一方、構造体の要素は、インスタンスごとに独立しています。メンバの値に加えられた変更は、他の構造体変数には反映されません。同じ Structure 宣言の他のインスタンスであっても反映されません。

  • 等値式 2 つの構造体の等価テストは、要素ごとに実行する必要があります。Equals メソッドを使用して、2 つのオブジェクト変数を比較できます。Equals は、2 つの変数が同じインスタンスを指しているかどうかを示します。

参照

処理手順

データ型のトラブルシューティング

概念

Visual Basic におけるデータ型

複合データ型

構造体とその他のプログラミング要素

値型と参照型

その他の技術情報

データ型の実装

構造体 : 独自のデータ型

クラスについて