C# 装箱/取消装箱是否通过后期或早期绑定(即在运行时或编译时)实现?

C# 装箱/取消装箱是否通过后期或早期绑定(即在运行时或编译时)实现?,c#,boxing,unboxing,C#,Boxing,Unboxing,例如: int i=10; object o = i; //late or early?? 同样地 object o = "11"; int i = (int)o;//late or early?? 编译器将发出您可以在IL中看到的装箱指令。给定代码 int item = 10; object obj = item; item = (int)obj; 您将编译成如下内容 IL_0000: ldc.i4.s 0A IL_0002: stloc.0 IL_0003: l

例如:

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

object o = "11";
int i = (int)o;//late or early??
编译器将发出您可以在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     
在第二个版本中,它会爆炸。字符串类型的对象不能转换为整数。

编译器将发出装箱指令,您可以在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类型的对象不能强制转换为整数。

如果您正在寻找整数,则装箱将在编译时烘焙到IL指令中

如果尝试取消装箱到原始类型以外的类型,将引发异常。Ex#1它恰好隐式地发生在box上(值类型转换为ref类型)。例2:一个无效的强制转换在运行时爆炸


不确定绑定的早到晚到什么程度。

如果您正在寻找的是装箱,则装箱将在编译时烘焙到IL指令中

如果尝试取消装箱到原始类型以外的类型,将引发异常。Ex#1它恰好隐式地发生在box上(值类型转换为ref类型)。例2:一个无效的强制转换在运行时爆炸

不确定绑定的早到晚到什么程度。

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

装箱需要(并非微不足道的)运行时成本;装箱和取消装箱可能会导致运行时错误(如您的示例“inti=(int)o”所示)

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

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

装箱需要(并非微不足道的)运行时成本;装箱和取消装箱可能会导致运行时错误(如您的示例“inti=(int)o”所示)

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

装箱和拆箱是通过后期绑定还是早期绑定实现的?也就是说,绑定是在运行时还是编译时完成的

我被这个问题弄糊涂了。“绑定”通常用于表示某种分析的结果。“早期绑定”通常意味着某些名称在编译时与某些方法槽相关联;“后期绑定”在运行时将名称与插槽相关联。在拳击比赛中,你所说的“捆绑”是什么意思

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

我不是这个意思;我使用方法调用作为一个规范示例,说明了早期绑定和后期绑定之间的区别。我现在更明白你的意思了;精确确定转换执行方式的分析也可以在运行时或编译时完成,因此在某种意义上也是“后期绑定”或“早期绑定”的一种形式

让我们以这种转换为例:

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

现在让我们稍微澄清一下:

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 x = Whatever();
object q = x;
int y = Convert.ToInt16(q);
在运行时抛出异常。在编译时,我们知道这是一个拆箱转换。在运行时,我们不会用“后期绑定”来表示“嘿,我有一个装箱的int,让我想想如何将它转换成一个未装箱的short”。相反,我们说“我们试图将int解装箱为short;抛出异常”。装箱的T只能解装箱到T或可为空的T

那么拆箱是“提前绑定”还是“延迟绑定”?它是早期绑定,因为我们在编译时知道它是一个拆箱转换。从我们在运行时进行类型检查的意义上讲,它是后期绑定的。从某种意义上说,我们不会在运行时重新进行编译时int-to-short转换的类型分析,这不是后期绑定

这个怎么样

int x = Whatever();
object q = x;
int y = (short)q;
int x = Whatever();
object q = x;
int y = Convert.ToInt16(q);

现在我们在运行时执行所有这些分析;在这两种情况下,我们都在运行时对q进行类型分析,确定q是一个装箱的int,并“后期绑定”转换

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

装箱和拆箱是通过后期绑定还是早期绑定实现的?也就是说,绑定是在运行时还是编译时完成的

我被这个问题弄糊涂了。“B