通过延迟或早期绑定(即在运行时或编译时)实现Boxing / unboxing?

时间:2011-12-07 04:12:30

标签: c# boxing unboxing

例如:

int i=10;
object o = i; //late or early??

类似地,

object o = "11";
int i = (int)o;//late or early??

4 个答案:

答案 0 :(得分:8)

  

通过延迟或早期绑定实施装箱和拆箱吗?也就是说,绑定是在运行时还是编译时完成的?

我对这个问题感到有些困惑。 “绑定”通常用于表示某种分析的结果。 “早期绑定”通常意味着某些名称在编译时与某些方法槽相关联; “后期绑定”在运行时将名称与插槽相关联。你在拳击的背景下“绑定”是什么意思?

  

我想你的意思是说,后期绑定仅用于方法和方法调用,而不用于赋值操作/类型转换。为了实现动态绑定,我们使用基类变量引用派生对象。

这不正是我的意思;我使用方法调用作为一个典型的例子来说明早期和晚期绑定之间的区别。我现在看到你的观点更好了;精确确定如何执行转换的分析也可以在运行时或编译时完成,因此在某种意义上也是“后期绑定”或“早期绑定”的形式。

我们以此转换为例:

int x = Whatever();
short y = (short)x;

显式转换在编译时完全“绑定”。编译器知道操作数是int,目标类型是short,转换将通过将四字节int截断为两个字节的短来执行。转换当然实际上是在运行时执行的。

现在让我们说清楚一点:

int x = Whatever();
short y = checked((short)x);

显式转换在编译时再次绑定。我们知道如何执行操作。但我们也知道在运行时将检查int值以确保它适合短

你的书中是否算作“迟到装订”?有些分析是在编译时执行的,但有些分析是在运行时执行的。

现在让我们考虑拳击:

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,让我弄清楚如何将其转换为未装箱的短片”。相反,我们说“我们试图将int取消装箱以缩短;抛出异常”。盒装T只能打包到T或可以为空的T。

拆箱“早期约束”还是“后期约束”?它是早期绑定的,因为我们在编译时知道它是一个拆箱转换。它是在运行时进行类型检查的意义上的后期绑定。从某种意义上说,我们没有在运行时重新进行在编译时进行int-to-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,并且“后绑定”转换。

这一切都清楚了吗?很难回答你的问题,因为对于“后期绑定”转换的确切含义,它有点模糊。分析的哪一部分是对你的“约束力”?

答案 1 :(得分:5)

如果你正在寻找的话,可以在编译时将装箱编入IL指令。

如果您尝试将unbox打包成原始类型以外的类型,则会抛出异常。 Ex#1它只是隐式地发生了(值类型为ref类型转换)。 Ex#2无效的演员阵容在运行时爆炸。

不确定早期或晚期的约束是如何形成的。

答案 2 :(得分:4)

编译器将发出您可以在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     

在第二个版本中,这只会爆炸。 string类型的对象不能转换为整数。

答案 3 :(得分:1)

C#编译在运行时执行的指令。

拳击需要(不可忽视的)运行时成本;装箱和拆箱会导致运行时错误(例如“int i =(int)o”​​示例)。

“后期绑定”与“早期绑定”意味着某些东西是“动态的”(例如,某些对象的虚拟方法的运行时绑定)。在这种情况下,拳击是“固定的”。所以我想你可以说它是“早期约束”。