在以下代码中......
int i=5;
object o = 5;
Console.WriteLine(o); //prints 5
我有三个问题:
1) 5
驻留在变量o
中的5
获取了变量i
代表的其他/有用功能} 不具有 ?
2)如果某些代码需要一个值类型,那么我们可以将它传递给int i
,但如果它期望一个引用类型,它可能对5盒装不感兴趣无论如何,在o
。那么什么时候在代码中明确使用装箱转换?
3)为什么Console.WriteLine(o)
打印出5而不是System.Object?
答案 0 :(得分:5)
变量i所代表的5所具有的变量o所具有的附加/有用功能是什么?
您想要包装内容很少见,但偶尔也需要 。在旧版本的.NET中,通常需要装箱,因为某些方法仅适用于object
(例如ArrayList的方法)。现在存在泛型问题,这不是一个问题,因此在较新的代码中更少发生装箱。
如果某些代码需要一个值类型,那么我们可以将它传递给int i,但是如果它期望一个引用类型,它可能不会对o中的5个盒子感兴趣。那么什么时候在代码中明确使用装箱转换?
在练习中,拳击通常会自动发生。如果你想让你的代码的读者更清楚拳击正在发生,你可以明确地选择一个变量。如果性能可能成为一个问题,这可能是相关的。
为什么Console.WriteLine(o)打印出5而不是System.Object ??
因为ToString
是object
上的虚方法,这意味着调用的实现取决于运行时类型,而不是静态类型。由于int
会使用自己的实现覆盖ToString
,因此调用的是int.ToString
,而不是object
提供的默认实现。
object o = 5;
Console.WriteLine(o.GetType()); // outputs System.Int32, not System.Object
答案 1 :(得分:0)
变量i所代表的5所代表的变量o所具有的附加/有用功能是什么?
除了可以通过引用需要它的代码传递它之外,没有盒装值类型获取的其他功能。
那么什么时候在代码中明确使用装箱转换?
当你需要明确地将int
打包到object
时,我不能自发地想到一个场景,因为在这个方向上总会有一个隐含的转换(虽然我不会感到惊讶如果有需要进行显式转换的情况)。
为什么Console.WriteLine(o)打印出5而不是System.Object ??
它在传递的对象上调用ToString
。事实上,它首先尝试将对象转换为IFormattable
,如果成功(将在int
的情况下),则调用ToString
overload that is defined in that interface。这将返回“5”。
答案 2 :(得分:0)
1)就其自身而言,没有多大意义。但是想象一下你希望以通用方式存储某些东西,而你不知道那个东西是值还是对象。使用装箱,您可以将值转换为对象,然后将所有内容视为对象。除此之外,您需要一个特殊情况才能保存值或一个对象。 (这在容器(例如列表)中最有用,允许您将诸如5之类的值与对象(如FileStream)的引用混合在一起。
2)拳击转换通常只是隐式发生,除了示例拳击的示例代码。
3)WriteLine代码可能调用虚拟Object.ToString()方法。如果它调用它的Object的类不重写ToString,那么它将调用基类(对象)实现,但大多数类型(包括System.Int虽然int是值类型,但它仍然派生自System.Object )覆盖它以提供更有用的特定于上下文的结果。
答案 3 :(得分:0)
附加功能:该对象是一个完整的对象。您可以在其上调用方法并像使用任何其他对象一样使用它:
System.Console.WriteLine("type: {0}", o.GetType());
System.Console.WriteLine("hash code: {0}", o.GetHashCode());
int变量是值类型,而不是对象。
XXX:这是不正确的;看评论。我冒昧地说,你可以使用这两者的一个区别是object o = 5
可以为空(你可以设置o = null
),而值类型不是 - 如果是int i = 5
,那么i
始终是一个int。
显式装箱:正如你所说,盒装版本是通过编码操纵对象作为对象而不是整数来使用的。这就是启用非类型安全通用数据结构的原因。现在可以使用类型安全的通用数据结构,你不太可能进行太多的转换和装箱/拆箱。
为什么是“5”:因为对象知道如何使用ToString()
打印自己。