ボックスアンドアンボックスはどういう意味ですか? [複製
質問
可能な複製:
なぜC#でボクシングとボクシングを解除する必要があるのですか?
ボクシングとアンボクシングとは何ですか、そしてトレードオフとは何ですか?
C#では、Doe Sitの意味:「Box and Unbox」?
ここに、テキストを設立したMSDNからの抜粋があります。
しかし、この利便性には費用がかかります。 ArrayListに追加された参照または値タイプは、オブジェクトに暗黙的にアップキャストされます。アイテムが値のタイプの場合、リストに追加されたときに箱詰めされ、取得したときにボックス化されていない必要があります。キャスティングとボクシングおよびアンボクシング操作の両方がパフォーマンスを低下させます。ボクシングとボクシングの効果は、大規模なコレクションを反復する必要があるシナリオでは非常に重要です。
ありがとう!
解決
一般的な言語ランタイムの内部を調べるより詳細な説明を以下に示します。
まず、違いを生み出しましょう 値タイプ と 参照タイプ:
- 値タイプが保持されます スタック そしてそのコピーは呼び出されたメソッドに渡されます
- 参照値はに保持されます マネージドヒープ スタックは、その場所へのポインター(参照)のみを保持します。オブジェクトではなく場所は、呼び出されたメソッドに渡されます
スタックが何であるか(気分を害さないでください)がわからない場合、それは使用されているメソッドと発信者関数のアドレスにローカル変数を保持するメモリ領域です return
指示(簡潔であり、一般的な答えを提供するためだけに)。メソッドを呼び出すと、スタック上の十分な領域が 静的に それに割り当てられているため、スタック割り当ては常に静的割り当てと呼ばれます。
ヒープは、代わりに、スタックから分離されたメモリ領域です。 財産 ランニングプロセスのオペレーティングシステムに最初に要求されなければならない、そしてそれがそれが呼ばれる理由です 動的割り当て (たとえば、IFステートメントで実行しない場合、メモリはプロセスに割り当てられない場合があります。代わりに、スタックは常に割り当てられます)。
ヒープとスタックで最終例を作成するために:C ++などの言語で、宣言 int[100] a;
スタックに100*8バイトを静的に割り当てます(64ビットシステムを想定)、 int* a = new int[100];
スタックの8バイト(64ビットシステム)領域を宣言し、ヒープでさらに800バイトを要求します。
さて、C#について話しましょう:
ボクシング
intは値タイプであり、スタックに割り当てられているため、オブジェクトまたは他の参照タイプにキャストすると(実際にはintが継承できる他の参照タイプはありませんが、一般的なルールです)参照タイプ。したがって、ヒープ上の新しい領域が割り当てられ、オブジェクトは 箱入り その中には、スタックがそれへのポインターを保持します。
ボックス化解除
ちょうど反対です:オブジェクトなどの参照タイプがあり、INTなどの値タイプにキャストしたい場合、CLRはヒープに移動するため、新しい値をスタックに保持する必要があります。 un-boxes 値とコピーをスタックにコピーします。
言い換えると
覚えておいてください int[]
と int*
例?単純に、あなたが持っているとき int
C#では、ランタイムはスタックの場所を期待しています 値を保持します しかし、代わりにあなたが持っているとき object
, 、その本当の価値は、スタックが指し示すヒープの場所にあると予想しています。
他のヒント
.NETフレームワークには2つの異なるタイプがあります。
ValueTypesINT、ダブル、シングルなど
参照タイプArrayListリストなど多く
タイプの変数 ValueTypes スタックに保存されます参照タイプ 変数はヒープに保存されます
タイプの変数 ValueTypes 値を保存します参照タイプ 変数は参照を値に保存します
したがって、コピーする場合 ValueType 変数 - があります 本当のコピー 値ですが、コピーする場合 参照タイプ 変数 - を取得します 追加の参照 同じ変数に。
質問のボクシングは、ValueType変数(例:int)が扱われることを意味しますリファレンスタイプ変数 - .NETはそれを新しいものに与えます 箱. 。そのため、ヒープ内でカプセル化され、参照があります。
値を再びValuEtype変数にしたい場合に備えて アンボックス それ(箱から出して)。そのため、値はヒープから取り出され、再びスタックに保存/与えられます。
ArrayListはオブジェクトのみを保存します。参照タイプの場合(次のように String
)これは問題ではありませんが、ValueType(int、datetime、..)の場合です。
これらのValuETypeは、プレーンオブジェクトとして保存する前に、オブジェクトに変換する必要があります。この「オブジェクトへの変換」は「ボクシング」と呼ばれ、少し時間がかかります。
値を読むときは、オブジェクトから変換する必要があります int
(またはそれが何であれ)。これは「ボックス化」と呼ばれます。