クラスまたは構造体の選択Choosing Between Class and Struct

すべてのフレームワークデザイナーの面で基本的な設計上の決定事項の1つは、型をクラスとしてデザインするか (参照型)、または構造体 (値型) として設計するかということです。One of the basic design decisions every framework designer faces is whether to design a type as a class (a reference type) or as a struct (a value type). この選択を行うには、参照型と値型の動作の違いをよく理解していることが重要です。Good understanding of the differences in the behavior of reference types and value types is crucial in making this choice.

参照型と値型の間の最初の違いは、参照型がヒープに割り当てられ、ガベージコレクトされるのに対し、値型はスタックまたはインラインの型に割り当てられ、スタックのアンワインドまたはそれを含んでいる型の割り当てが解除されるときに割り当てが解除されるという点です。The first difference between reference types and value types we will consider is that reference types are allocated on the heap and garbage-collected, whereas value types are allocated either on the stack or inline in containing types and deallocated when the stack unwinds or when their containing type gets deallocated. したがって、値型の割り当てと割り当て解除は、参照型の割り当てと割り当て解除よりも一般的に低コストです。Therefore, allocations and deallocations of value types are in general cheaper than allocations and deallocations of reference types.

次に、参照型の配列はアウトオブラインで割り当てられます。つまり、配列要素は、ヒープに存在する参照型のインスタンスへの参照にすぎません。Next, arrays of reference types are allocated out-of-line, meaning the array elements are just references to instances of the reference type residing on the heap. 値型の配列はインラインで割り当てられます。つまり、配列要素は値型の実際のインスタンスです。Value type arrays are allocated inline, meaning that the array elements are the actual instances of the value type. したがって、値型の配列の割り当てと割り当て解除は、参照型の配列の割り当てと割り当て解除よりもはるかに安価です。Therefore, allocations and deallocations of value type arrays are much cheaper than allocations and deallocations of reference type arrays. また、ほとんどの場合、値型の配列は参照の局所性が大幅に向上します。In addition, in a majority of cases value type arrays exhibit much better locality of reference.

次の相違点は、メモリ使用量に関連します。The next difference is related to memory usage. 参照型または実装するインターフェイスのいずれかにキャストすると、値型はボックス化されます。Value types get boxed when cast to a reference type or one of the interfaces they implement. 値型にキャストされると、ボックス化が解除されます。They get unboxed when cast back to the value type. ボックスはヒープに割り当てられ、ガベージコレクトされるオブジェクトであるため、ボックス化とボックス化解除が過剰になると、ヒープ、ガベージコレクター、および最終的にアプリケーションのパフォーマンスに悪影響を及ぼす可能性があります。Because boxes are objects that are allocated on the heap and are garbage-collected, too much boxing and unboxing can have a negative impact on the heap, the garbage collector, and ultimately the performance of the application. これに対し、参照型がキャストされると、このようなボックス化は行われません。In contrast, no such boxing occurs as reference types are cast. (詳細については、「ボックス化とボックス化解除」を参照してください)。(For more information, see Boxing and Unboxing).

次に、参照型の割り当てによって参照がコピーされます。一方、値型の割り当てでは、値全体がコピーされます。Next, reference type assignments copy the reference, whereas value type assignments copy the entire value. したがって、大きな参照型の割り当ては、大きな値型の割り当てよりもコストが高くなります。Therefore, assignments of large reference types are cheaper than assignments of large value types.

最後に、参照型は参照によって渡されるのに対し、値型は値によって渡されます。Finally, reference types are passed by reference, whereas value types are passed by value. 参照型のインスタンスへの変更は、そのインスタンスを指すすべての参照に影響します。Changes to an instance of a reference type affect all references pointing to the instance. 値型のインスタンスは、値によって渡されるときにコピーされます。Value type instances are copied when they are passed by value. 値型のインスタンスが変更された場合、当然、そのインスタンスのコピーには影響しません。When an instance of a value type is changed, it of course does not affect any of its copies. コピーはユーザーによって明示的に作成されるのではなく、引数が渡されるときに暗黙的に作成されるため、または戻り値が返される場合、変更可能な値型は多くのユーザーに混乱を招く可能性があります。Because the copies are not created explicitly by the user but are implicitly created when arguments are passed or return values are returned, value types that can be changed can be confusing to many users. したがって、値型は不変である必要があります。Therefore, value types should be immutable.

経験則として、フレームワークのほとんどの型はクラスである必要があります。As a rule of thumb, the majority of types in a framework should be classes. ただし、場合によっては、値型の特性によって、構造体を使用する方が適切であることがあります。There are, however, some situations in which the characteristics of a value type make it more appropriate to use structs.

型のインスタンスが小さく、通常は短い有効期間であるか、または他のオブジェクトに埋め込まれている場合は、クラスではなく構造体を定義する✔️ます。✔️ CONSIDER defining a struct instead of a class if instances of the type are small and commonly short-lived or are commonly embedded in other objects.

❌型に次の特性がすべて含まれている場合を除き、構造体を定義しないでください。❌ AVOID defining a struct unless the type has all of the following characteristics:

  • プリミティブ型 (、など) と同様に、論理的には単一の値を表し int double ます。It logically represents a single value, similar to primitive types (int, double, etc.).

  • インスタンスのサイズは16バイト未満です。It has an instance size under 16 bytes.

  • 変更できません。It is immutable.

  • 頻繁にボックス化する必要はありません。It will not have to be boxed frequently.

それ以外の場合は、型をクラスとして定義する必要があります。In all other cases, you should define your types as classes.

©2005、2009 Microsoft Corporation の部分。すべての権限が予約されています。Portions © 2005, 2009 Microsoft Corporation. All rights reserved.

2008 年 10 月 22 日に Microsoft Windows Development シリーズの一部として、Addison-Wesley Professional によって発行された、Krzysztof Cwalina および Brad Abrams による「Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition」 (フレームワーク デザイン ガイドライン: 再利用可能な .NET ライブラリの規則、用法、パターン、第 2 版) から Pearson Education, Inc. の許可を得て再印刷されています。Reprinted by permission of Pearson Education, Inc. from Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition by Krzysztof Cwalina and Brad Abrams, published Oct 22, 2008 by Addison-Wesley Professional as part of the Microsoft Windows Development Series.

関連項目See also