例:
int i=10;
object o = i; //late or early??
同様に、
object o = "11";
int i = (int)o;//late or early??
ボックス化とボックス化解除は、遅延バインディングまたは早期バインディングによって実装されていますか? つまり、バインディングは実行時またはコンパイル時に行われますか?
私はその質問に少し混乱しています。「バインディング」は通常、何らかの分析の結果を意味するために使用されます。「アーリー バインディング」とは通常、コンパイル時に何らかの名前が何らかのメソッド スロットに関連付けられていることを意味します。「遅延バインディング」は、実行時に名前をスロットに関連付けます。ボクシングの文脈で、ここで「縛る」とはどういう意味ですか?
レイト バインディングは、メソッドとメソッド呼び出しに対してのみ機能し、代入操作/型変換に対しては機能しないと言っているのだと思います。動的バインディングを実装するには、派生オブジェクトを基本クラス変数で参照します。
それはまさに私が言いたかったことではありません。アーリー バインディングとレイト バインディングの違いを示す標準的な例として、メソッド呼び出しを使用していました。私はあなたの主張をよりよく理解しています。変換がどのように実行されるかを正確に決定する分析は、実行時またはコンパイル時にも実行できるため、ある意味では「遅延バインディング」または「早期バインディング」の形式でもあります。
例として、この変換を見てみましょう:
int x = Whatever();
short y = (short)x;
その明示的な変換は、コンパイル時に完全に「バインド」されます。コンパイラは、オペランドが int であること、ターゲットの型が short であること、4 バイトの int を 2 バイトの short に切り捨てることによって変換が実行されることを認識しています。もちろん、変換は実行時に実際に実行されます。
ここで、もう少し明確にしましょう。
int x = Whatever();
short y = checked((short)x);
明示的な変換は、コンパイル時に再度バインドされます。操作がどのように実行されるかはわかっています。しかし、実行時に int 値がチェックされ、 short に収まるかどうかが確認されることもわかっています。
それはあなたの本では「遅延バインディング」と見なされますか? 一部の分析はコンパイル時に実行されますが、一部の分析は実行時に実行されます。
次にボクシングについて考えてみましょう。
int x = Whatever();
object q = x;
これはコンパイル時に完全に分析されます。コンパイラは、q がオブジェクトで x が int であることを認識しているため、実行時に int をボックス化する命令を発行する必要があります。
開梱についてはどうですか?
int x = Whatever();
object q = x;
int y = (int)q;
コンパイル時にどのような分析が行われますか? コンパイル時にわかっているのは、それがボックス化解除の変換であることだけです。実際の型チェックは実行時に行われます。遅延バインディングの定義により、実行時に型チェックが実行されるため、それは「遅延バインディング」の形式ですか?
これはどう?
int x = Whatever();
object q = x;
int y = (short)q;
これにより、実行時に例外がスローされます。コンパイル時に、それがボックス化解除の変換であることがわかります。実行時に、「ねえ、ボックス化された int があるので、それをボックス化されていない short に変換する方法を考えさせてください」という「レイト バインディング」は行いません。むしろ、「int を short に unbox しようとしています。例外をスローします」と言います。ボックス化された T は、T または nullable T にのみアンボックス化できます。
では、ボックス化解除は「アーリー バウンド」または「レイト バウンド」ですか? これは、コンパイル時にアンボックス変換であることがわかっているという意味で、事前にバインドされています。実行時に型チェックを行うという意味で、遅延バインディングです。コンパイル時に int から short への変換のために行われるであろう型分析を実行時にやり直さないという意味では、遅延拘束ではありません。
これはどうですか?
int x = Whatever();
object q = x;
int y = Convert.ToInt16(q);
また
int x = Whatever();
dynamic q = x;
int y = (int)q;
これで、すべての分析が実行時に実行されます。どちらの場合も、実行時に q の型分析を行い、q がボックス化された int であることを判断し、変換を「レイト バインド」します。
それはすべて明確ですか?変換を「遅延バインディング」することの正確な意味が少し曖昧であるため、質問に答えるのは難しいです。分析のどの部分があなたにとって「拘束力」がありますか?
それがあなたが探しているものである場合、ボクシングはコンパイル時にIL命令に組み込まれます。
元の型以外の型にボックス化解除しようとすると、例外がスローされます。Ex#1 たまたま暗黙的にボックス化する (値型から ref 型へのキャスト)。Ex#2 無効なキャストが実行時に爆発する。
早いバインディングまたは遅いバインディングがどのように登場するかはわかりません。
コンパイラは、IL で確認できるボクシング命令を出力します。指定されたコード
int item = 10;
object obj = item;
item = (int)obj;
次のようなものにコンパイルします
IL_0000: ldc.i4.s 0A
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: box System.Int32
IL_0009: stloc.1
IL_000A: ldloc.1
IL_000B: unbox.any System.Int32
IL_0010: stloc.0
2番目のバージョンでは、それは爆発するだけです. 文字列型のオブジェクトは整数にキャストできません。
C# は、実行時に実行される命令をコンパイルします。
ボックス化には、(無視できないほどの) ランタイム コストが伴います。ボックス化とボックス化解除により、実行時エラーが発生する可能性があります(例「int i = (int)o」が示すように)。
「遅延バインディング」と「早期バインディング」は、何かが「動的」であることを意味します (たとえば、一部のオブジェクトの仮想メソッドの実行時バインディング)。この場合、ボクシングは「固定」です。つまり、「アーリー バインディング」と言えるのではないでしょうか。