Boxing是将值类型转换为托管堆对象的过程,这是隐式的。拆箱是反向过程,编译器需要显式转换。由于拳击存储数据类型,为什么不能拆箱使用它而不是要求显式转换?
class BoxUnBox
{
static void Main()
{
int i = 123; // a value type
object o = i; // boxing
int j = (int)o; // unboxing - Why is an explicit cast required?
}
}
答案 0 :(得分:42)
您的问题仅与拆箱操作无关。实际上它应该听起来像“我为什么要使用显式转换?”请考虑以下示例:
int i = 123;
long l = i;
int j = (int)l; // OMG why??
答案很简单,您可以在C#规范6.2 Explicit conversions中找到它:
明确的转化是无法证明的转化 总是成功,已知的转换可能会丢失 信息,以及跨类型域的转换 不同于值得明确的符号。
在上面的示例中,您可能丢失信息,因为long
可以包含不符合int
范围的值。但在将int
分配给long
时,您永远不会丢失信息:
long l = i; // safe
在您的示例中,您需要显式转换,因为隐式转换无法证明始终成功。 object
类型的变量可以参考
字面上任何类型。串怎么样?
object o = i; // implicit and always safe
o = "Now I have a machinegun ho-ho-ho"; // safe too
int j = o; // will not succeed if o is string
<强>类比强>
对象变量就像一个黑盒子,你可以放任何东西 - 音乐CD,笔,电话或香蕉。不仅是你,而且任何人都可以在那里放东西。如果你早上放在黑匣子里的最后一件东西是香蕉,你能否在晚上回来吃掉从黑匣子里拿出来的东西?如果你独自生活,房间关闭,你的记忆非常好,那么......你可以。你会想知道为什么每个人在吃之前检查他们的盒子的内容。但是,如果你不是一个人住,或房间没有关闭,或者你可以忘记一次,你把手机放入盒子......好胃口
答案 1 :(得分:6)
如果有人将o
的内容更改为"Hello World"
,该怎么办?为了确保您知道自己在做什么,编译器要求您明确地转换盒装值。
基本上,隐式转换意味着类型为object的任何实例o
也可以表示为int
的实例,但事实并非如此。例如考虑这个:
int i = -1;
long j = i;
很明显,您的变量i
(整数)也可以视为long
。这就是隐式铸造在这里准确的原因。另一方面,并非每个long
也可以转换为int
而不会丢失任何数据。因此,您需要一个显式的强制转换来确定:我知道可能会丢失一些数据,但我并不关心它。
答案 2 :(得分:5)
由于Int32
为Object
,但Object
可能为Int32
。
编译器知道在第一种情况下该做什么,但你必须告诉编译器你知道你在第二种情况下做了什么,并保证可以执行拆箱。
继承关系是方向性的!父母与孩子不同。
答案 3 :(得分:4)
任何int都可以转换为对象。并非所有对象都可以转换为整数。
答案 4 :(得分:3)
编译器无法保证对象内部的内容。这就是为什么你需要显式地转换为你期望的值。对于编译器:
这是危险的
object o = 45;
int j = (int)o;
这样:
object o = "something";
int j = (int)o;
编译时不允许这样做。
答案 5 :(得分:2)
在运行时,转换可能会失败,具体取决于object
真正包含的内容。当隐式拆箱是可能的时候,你可能会忽略错误,因为你可能写了一些不同的意思(由你或你误解了别人的代码)。编译器要求您明确强制转换,因为您应该真正想要进行强制转换。否则,您可能会错误地混合类型,从而产生容易出错的代码。如果被迫明确施展,你被迫三思而后行,如果你所做的是对的。
答案 6 :(得分:1)
不要忘记已经说过的任何内容,但我想指出,从技术上讲,执行拆箱并不总是需要演员表。动态关键字允许系统自动执行拆箱和转换。我既不建议也不劝阻使用动态,只是指出它的行为。
static void DynamicTest()
{
int i = 123; // a value type
object o = i; // boxing
dynamic d = o; // shift to dynamic
int j = d; // unboxing - No cast required
}
编辑:Jeroen Mostert明智地指出,动态关键字并不是任何一种总能让它发挥作用的魔力。它只是将评估推迟到运行时行为。因此,虽然上面的示例将始终有效,但更复杂的示例肯定会失败。因此,在使用dynamic关键字并期望(try / catch)运行时失败时必须小心。如果明智地使用,动态关键字可以是一个非常强大的工具。