注
このコンテンツは、 フレームワーク設計ガイドライン (再利用可能な .NET ライブラリの規則、イディオム、パターン、第 2 版) から、Pearson Education, Inc. のアクセス許可によって再印刷されます。 そのエディションは2008年に出版され、その後 、本は第3版で完全に改訂されています。 このページの情報の一部が古くなっている可能性があります。
フレームワーク デザイナーが直面する基本的な設計上の決定事項の 1 つは、型をクラス (参照型) として設計するか、構造体 (値型) として設計するかです。 この選択を行うには、参照型と値型の動作の違いをよく理解することが重要です。
最初に考慮する参照型と値型の違いは、参照型がヒープとガベージ コレクションに割り当てられるのに対し、値型はスタック上または格納型のインラインに割り当てられ、スタックがアンワインドされたとき、または格納型が割り当て解除されたときに割り当てが解除される点です。 したがって、値型の割り当てと割り当て解除は、一般に参照型の割り当てと割り当て解除よりも低くなります。
次に、参照型の配列は行外に割り当てられます。つまり、配列要素は、ヒープ上に存在する参照型のインスタンスへの参照にすぎません。 値型配列はインラインで割り当てられます。つまり、配列要素は値型の実際のインスタンスです。 したがって、値型配列の割り当てと割り当て解除は、参照型配列の割り当てと割り当て解除よりもはるかに安価です。 さらに、ほとんどの場合、値型の配列は参照の局所性がはるかに優れています。
次の違いは、メモリ使用量に関連しています。 参照型または実装されているインターフェイスのいずれかにキャストすると、値型がボックス化されます。 値型にキャストバックすると、ボックス化解除されます。 ボックスはヒープに割り当てられ、ガベージ コレクションされるオブジェクトであるため、ボックス化とボックス化解除が多すぎると、ヒープ、ガベージ コレクター、および最終的にはアプリケーションのパフォーマンスに悪影響を与える可能性があります。 これに対し、参照型がキャストされるため、このようなボックス化は行われません。 (詳細については、「 ボックス化とボックス化解除」を参照してください)。
次に、参照型の割り当てによって参照がコピーされ、値型の割り当てによって値全体がコピーされます。 そのため、大きな参照型の割り当ては、大きな値型の割り当てよりも安価です。
最後に、参照型は参照によって渡されますが、値型は値によって渡されます。 参照型のインスタンスに対する変更は、インスタンスを指すすべての参照に影響します。 値型インスタンスは、値渡し時にコピーされます。 値型のインスタンスが変更された場合、そのコピーには影響しません。 コピーはユーザーによって明示的に作成されるのではなく、引数が渡されるか戻り値が返されたときに暗黙的に作成されるため、変更できる値型は多くのユーザーに混乱を招く可能性があります。 したがって、値型は不変である必要があります。
経験則として、フレームワーク内の型の大部分はクラスである必要があります。 ただし、値型の特性によって構造体の使用がより適切になる状況もあります。
✔️ 型のインスタンスが小さく、一般的に有効期間が短い場合、または他のオブジェクトに一般的に埋め込まれている場合は、クラスの代わりに構造体を定義することを検討してください。
❌ 型に次の特性がすべて含まれている場合を除き、構造体の定義は避けてください。
プリミティブ型 (
int
、double
など) と同様に、1 つの値を論理的に表します。インスタンス サイズは 16 バイト以下です。
変更できません。
頻繁にボックス化する必要はありません。
それ以外の場合は、型をクラスとして定義する必要があります。
Portions © 2005, 2009 Microsoft Corporation. 無断転載を禁じます。
フレームワーク設計ガイドライン:再利用可能な .NET ライブラリの規則、イディオム、パターン、Krzysztof Cwalina および Brad Abrams による第 2 版は、2008 年 10 月 22 日に Microsoft Windows 開発シリーズの一部として Addison-Wesley Professional によって公開されました。