12

重複の可能性:
C#でボクシングとアンボクシングが必要なのはなぜですか?
ボクシングとアンボクシングとは何ですか?トレードオフは何ですか?

C#では、doesitは「BoxandUnBox」とはどういう意味ですか?

これは、私がテキストを作成したMSDNからの抜粋です。

しかし、この便利さには代償が伴います。ArrayListに追加される参照または値の型は、暗黙的にObjectにアップキャストされます。項目が値型の場合、リストに追加するときにボックス化し、取得するときにボックス化を解除する必要があります。キャスティングとボクシングおよびアンボクシングの両方の操作により、パフォーマンスが低下します。大規模なコレクションを反復処理する必要があるシナリオでは、ボックス化とボックス化解除の効果が非常に重要になる可能性があります。

ありがとう!

4

3 に答える 3

28

これは、共通言語ランタイムの内部を調べるより詳細な説明です。

まず、値型参照型を区別してみましょう。

  • 値型はスタックに保持され、そのコピーが呼び出されたメソッドに渡されます
  • 参照値は管理対象ヒープに保持され、スタックはその場所へのポインター(参照)のみを保持します。オブジェクトではなく、場所が呼び出されたメソッドに渡されます

スタックが何であるかわからない場合(気分を害しないでください)、それはメソッド内のローカル変数とreturn命令に使用される呼び出し元関数のアドレスを保持するメモリ領域です(簡単に説明して一般的な答えを提供します)。メソッドを呼び出すと、スタック上の十分な領域が静的に割り当てられるため、スタックの割り当ては常に静的割り当てと呼ばれます。

代わりに、ヒープは、実行中のプロセスのプロパティであるスタックから分離されたメモリ領域であり、オペレーティングシステムに最初に割り当てを要求する必要があるため、動的割り当てと呼ばれます(ifステートメントで実行しない場合)。たとえば、メモリがプロセスに割り当てられていない場合、代わりにスタックが常に割り当てられます)。

ヒープとスタックの最後の例を示すために:C ++などの言語では、宣言するとスタックint[100] a;に100 * 8バイトが静的に割り当てられ(64ビットシステムを想定)、int* a = new int[100];宣言すると8バイト(64ビットシステムの場合)の領域が宣言されます。スタックANDは、使用可能な場合、ヒープ上にさらに800バイトを要求します。

それでは、C#について話しましょう。

ボクシング

intは値型であり、スタックに割り当てられるため、オブジェクトまたは他の参照型にキャストする場合(実際には、intが継承できる他の参照型はありませんが、原則として)、値は必然的になる必要があります。参照型。そのため、ヒープ上の新しい領域が割り当てられ、オブジェクトはその中にボックス化され、スタックはその領域へのポインタを保持します。

開箱

正反対です。オブジェクトなどの参照型があり、それをintなどの値型にキャストする場合は、新しい値をスタックに保持する必要があるため、CLRはヒープに移動し、ボックスを解除します。値を設定し、スタックにコピーします。

言い換えると

int[]int*例を覚えていますか?簡単に言うと、intC#を使用している場合、ランタイムはスタックの場所が値を保持することを期待しますがobject、代わりに、を使用している場合、実際の値はスタックが指すヒープの場所にあることを期待します。

于 2011-01-25T14:50:38.810 に答える
1

.netFrameworkには2つの異なるタイプがあります。

int、double、singleなどのValueTypes

ReferenceTypesArrayList リストおよびその他多数

タイプValueTypesの変数はスタック に格納されますReferenceTyped変数はヒープに格納されます

ValueTypes型の変数は、VALUE ReferenceTyped変数を格納し、REFERENCEを値に格納します。

したがって、ValueType変数をコピーすると(値の実際のコピーがありますが、 ReferenceType変数をコピーすると)、同じ変数への追加の参照が取得されます。

質問のボックス化は、valueType変数(intなど)が参照型変数のように処理されることを意味します-.netはそれを新しいボックスに入れます。したがって、ヒープ内にカプセル化され、それへの参照があります。

値をvalueType変数に再び入れたい場合は、ボックスを解除する必要があります(ボックスから取り出します)。したがって、値はヒープから取り出され、スタックに再度格納/提供されます。

于 2011-01-25T14:49:52.657 に答える
0

ArrayListはオブジェクトのみを格納します。参照型(のようなString)の場合、これは問題ありませんが、ValueType(int、DateTime、..)の場合は問題です。

これらの値型は、プレーンオブジェクトとして保存する前に、オブジェクトに変換する必要があります。この「オブジェクトへの変換」は「ボクシング」と呼ばれ、少し時間がかかります。

値を読み戻すときは、オブジェクトからint(またはそれが何であれ)に変換する必要があります。これは「開梱」と呼ばれます。

于 2011-01-25T14:42:51.197 に答える