質問
ボクシングは人気のある概念であり、多くの情報が利用可能であることは知っていますが、いくつかの質問がありますが、実際には答えが見つかりません:
1)ボックス化によって値型(構造体)がオブジェクト(参照型)または参照型に変換される場合、なぜボックス化されてパフォーマンスが低下する値型を使用するのですか?構造体またはクラスの特定の場合の利点と適合性を認識しています。 (1)値(値型)は、一時記憶領域のスタック上に存在する傾向があると言われていますが、どのくらいの期間ですか?タイプが必要ない場合、その時点でそのタイプが処理され、破棄されることをどのように確認できますか?それとも、使い捨てのパターンが効いてくるのでしょうか?構造体を使用する理由は、その利点によると思われます。
興味深いことに、構造体を使用して2つの文字列とDateTimeフィールドを格納する場合、構造体は2つの参照(文字列)とDateTimeを一緒に保持します。私は明らかに、これは散らばっている値よりも速いと思います。この設計で注意する必要があるものはありますか? (2)。
1) http://en.csharp-online .net / Classes、構造体、およびオブジェクト—ボックス化とボックス化解除
2) http://dotnetperls.com/Content/Struct-Examples.aspx
ここで、自分が求めている答えを探しましたが、運はありません。 GC、ジェネリック、例外処理などのトピックについては、このサイトで検索を行います。多くの知恵と学びがあります。
すべてのポスターに対する(潜在的な)教育に感謝します!潜在的な素朴さを許してください。内部を知ることで、ILなどの理解に少し時間を費やすことができます(すぐに取り組むべきことです)。
解決
値の型を参照変数に渡さない場合、ボクシングは発生しません。わからない場合は、次の質問に回答してくださいa>:
- プリミティブ型のように振る舞います。
- インスタンスサイズは16バイト未満にします。
- 不変です。
- 値のセマンティクスが望ましい。
私は通常、そのような変数の存続期間を検討します。メソッド内で使用されるローカル変数の場合は、struct(そうでない場合はクラス)を使用します。
他のヒント
パフォーマンスの向上ではなく、論理的な利点があるため、値型を使用する必要があります。つまり、値型はスタックで管理されるため、ガベージコレクションに参加する必要はありません。常に作成および破棄される型(int、float、doubleなど)がある場合は、これらを構造体に変換することで、大幅に向上できます。注意すべきことは、構造体を不変にすることもできる場合にのみ、実際にこれを考慮する必要があるということです。
考慮すべき他のいくつかのこと-
まず、構造体が不変であることを確認します(一般的に)。このため、参照型を含む構造体を持たないことをお勧めします。文字列はC#では不変であるため、例外になる場合がありますが、設計の汎用的な経験則の観点から、これには注意が必要です。
第二に、これまで言及されていなかった構造体の別のユースケースがあります-多数の小さなオブジェクト。大きなオブジェクトのリストまたは小さなオブジェクトの配列がある場合、構造体はキャッシュの一貫性を劇的に向上させるため、非常に重要です。これが、ほとんどの3Dエンジンがポイント/ベクトルに構造体を使用する理由です-頂点などに大きなポイントの配列がある傾向があります。
これは、アプリケーションのパフォーマンスが重要な部分であるかどうかに注意する価値があります。たとえば、私のアプリの1つで、単一のタイプをクラスから構造体に変更すると、長時間実行(> 5分間の実行)プロセスが40%削減されました。重度の数学計算で繰り返し使用している場合、オブジェクトをメモリ内で互いに近づけることで、大きなメリットが得られます。
今-あなたの場合、2つの文字列とDateTimeを持っていることはおそらくこれからの改善を見ないでしょう。文字列で動作するルーチンのタイプは、おそらく、(うまくいけば)重い計算を実行していません。つまり、空間で50万ポイントを変換するか、大規模な行列ソリューションを実行するなどです。
最後に、.net3.5sp1が構造体をより便利にしたことに気付くでしょう。 3.5sp1(x86)より前は、struct呼び出しを使用したメソッドのインライン化はありませんでした。これにより、構造体を介して可能なパフォーマンスの向上が制限されました。フレームワークを更新すると、古い構造体コードがはるかに高速になります(特定の場合)。
ボクシングは必ずしも必要ではありません。ジェネリックでは、ほとんど必要ありません。
値型(構造体は値型)が使用するメモリは、
メソッドが終了/戻るとすぐに、そのために何もする必要はありません。
インスタンスメンバーとして宣言された値型は、オブジェクト
GCによって削除されます。
参照タイプは管理ヒープに保持されます。
メソッド内でインスタンス化された参照型は、
オブジェクトへの参照を保持しているオブジェクトがない場合のガベージコレクター。
GCは単独で動作し、ほとんどの場合、そのままにしておく必要があります。
オブジェクトがGCによって削除される時期を予測することはできません。
Disposeパターンは参照型で使用されますが、GCを強制的に削除することはありません
オブジェクト。通常、アンマネージリソースを解放するために使用されます。
スタック内の値については、以下を考慮してください:
次のような3つのメソッドを持つ単純なプログラムがあるとします。
このプログラムが実行されると、Mainメソッドが実行されます。フォローしてください
以下の番号:
Main
{
// (0) Stack is empty
int firstInt = 0;
// (1) Stack now contains:
// firstInt
DoSomething1();
// (7) Stack still contains:
// firstInt
}
// Program ends
DoSomething()
{
int anInteger = 0;
// (2) Stack now contains:
// anInteger
// firstInt
DoMore()
// (5) Stack now contains:
// anInteger
// firstInt
}
// (6) anInteger goes out of scope
DoMore
{
int anotherInteger = 1;
// (3) Stack now contains:
// anotherInteger
// anInteger
// firstInt
}
// (4) anotherInteger goes out of scope
<コード>