关于拳击价值类型的困惑

时间:2010-10-19 21:10:17

标签: c#

在以下代码中......

 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?

4 个答案:

答案 0 :(得分:5)

  

变量i所代表的5所具有的变量o所具有的附加/有用功能是什么?

想要包装内容很少见,但偶尔也需要 。在旧版本的.NET中,通常需要装箱,因为某些方法仅适用于object(例如ArrayList的方法)。现在存在泛型问题,这不是一个问题,因此在较新的代码中更少发生装箱。

  

如果某些代码需要一个值类型,那么我们可以将它传递给int i,但是如果它期望一个引用类型,它可能不会对o中的5个盒子感兴趣。那么什么时候在代码中明确使用装箱转换?

在练习中,拳击通常会自动发生。如果你想让你的代码的读者更清楚拳击正在发生,你可以明确地选择一个变量。如果性能可能成为一个问题,这可能是相关的。

  

为什么Console.WriteLine(o)打印出5而不是System.Object ??

因为ToStringobject上的虚方法,这意味着调用的实现取决于运行时类型,而不是静态类型。由于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()打印自己。