クラスまたは構造体の選択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.

X 次の条件をすべて満たさない限り、構造体を**定義しないでください。X AVOID defining a struct unless the type has all of the following characteristics:

  • プリミティブ型 (intdoubleなど) のように、論理的に 1 つの値を表す。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.

Portions © 2005, 2009 Microsoft Corporation.All rights reserved.Portions © 2005, 2009 Microsoft Corporation. All rights reserved.

Pearson Education, Inc. からのアクセス許可によって了承を得て転載Framework デザイン ガイドライン。規則、手法、および再利用可能な .NET ライブラリの第 2 版のパターンKrzysztof Cwalina、Brad 内容では、Microsoft Windows の開発シリーズの一部として、Addison-wesley Professional、2008 年 10 月 22日を公開します。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