为什么拆箱需要在C#中进行显式转换?

时间:2017-02-22 11:48:56

标签: c# casting unboxing

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?
 }
}

7 个答案:

答案 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)

使用Dynamic可以避免强制转换

不要忘记已经说过的任何内容,但我想指出,从技术上讲,执行拆箱并不总是需要演员表。动态关键字允许系统自动执行拆箱和转换。我既不建议也不劝阻使用动态,只是指出它的行为。

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)运行时失败时必须小心。如果明智地使用,动态关键字可以是一个非常强大的工具。