構造体は、本質的にはフィールドの集合体にすぎません。.NETでは、構造体がオブジェクトであるように "偽装"することが可能であり、.NETの各構造体タイプでは、ヒープオブジェクトであるオブジェクトと同じように動作する同じフィールドとメソッドを持つヒープオブジェクトタイプを暗黙的に定義します。 。そのようなヒープオブジェクト(「ボックス化」構造)への参照を保持する変数は、参照セマンティクスを示しますが、構造体を直接保持する変数は、単に変数の集約です。
構造体とクラスの混同の多くは、構造体には2つの非常に異なる使用例があり、非常に異なる設計ガイドラインが必要であるという事実に起因すると思いますが、MSガイドラインではそれらを区別しません。オブジェクトのように動作するものが必要になる場合があります。その場合、MSガイドラインはかなり妥当ですが、「16バイトの制限」はおそらく24-32に近いはずです。ただし、場合によっては、変数の集計が必要になることがあります。その目的で使用される構造体は、一連のパブリックフィールド、および場合によってはEquals
オーバーライド、ToString
オーバーライド、およびIEquatable(itsType).Equals
実装。フィールドの集約として使用される構造はオブジェクトではなく、そのように見せかけるべきではありません。構造の観点から見ると、フィールドの意味は「このフィールドに最後に書き込まれたもの」に過ぎない、またはそれ以下である必要があります。追加の意味は、クライアントコードで決定する必要があります。
たとえば、変数を集計する構造体にメンバーMinimum
andがあるMaximum
場合、構造体自体はそのことを約束してはなりませんMinimum <= Maximum
。このような構造をパラメーターとして受け取るコードは、個別の値Minimum
とMaximum
値が渡されたかのように動作する必要があります。要件Minimum
よりも大きくないMaximum
ことを要件と同様に見なされるべきMinimum
パラメータが別々に渡さより大きくないMaximum
1。
時々考慮すべき有用なパターンは、ExposedHolder<T>
クラスを以下のように定義することです:
class ExposedHolder<T>
{
public T Value;
ExposedHolder() { }
ExposedHolder(T val) { Value = T; }
}
変数集約構造体があるを持っている場合List<ExposedHolder<someStruct>>
、のsomeStruct
ようなことをすることができますmyList[3].Value.someField += 7;
がmyList[3].Value
、他のコードに与えると、Value
それを変更する手段を与えるのではなく、のコンテンツを与えます。対照的に、を使用した場合List<someStruct>
、を使用する必要がありますvar temp=myList[3]; temp.someField += 7; myList[3] = temp;
。可変クラス型を使用する場合、のコンテンツmyList[3]
を外部コードに公開するには、すべてのフィールドを他のオブジェクトにコピーする必要があります。不変のクラス型または「オブジェクトスタイル」の構造体を使用した場合は、異なるものmyList[3]
を除いて同様のsomeField
新しいインスタンスを作成し、その新しいインスタンスをリストに格納する必要があります。
追加の注意点:多数の類似のものを格納する場合は、ネストされている可能性のある構造の配列に格納することをお勧めします。できれば、各配列のサイズを1Kから64K程度に保つようにしてください。構造体の配列は特別です。インデックスを付けると、構造体内の直接参照が生成されるため、「a [12] .x = 5;」と言うことができます。配列のようなオブジェクトを定義できますが、C#ではそのような構文を配列と共有することはできません。