代码之家  ›  专栏  ›  技术社区  ›  explorer

关于值类型装箱的混淆

c#
  •  3
  • explorer  · 技术社区  · 14 年前

    在下面的代码中。。。

     int i=5;  
     object o = 5;
     Console.WriteLine(o); //prints 5
    

    (一) 哪些附加/有用的功能是由 5 o 那个 由变量表示 i 没有吗?

    如果某些代码需要值类型,那么我们可以将int o型 无论如何。那么代码中何时显式地使用装箱转换呢?

    为什么 Console.WriteLine(o)

    4 回复  |  直到 14 年前
        1
  •  5
  •   Mark Byers    14 年前

    驻留在变量o中的5获得了哪些额外/有用的功能,而变量o所表示的5没有这些功能?

    你很少 装东西,但有时 这样做。在旧版本的.NET中,装箱通常是必需的,因为有些方法只与 object (例如ArrayList的方法)。既然有了泛型,这就不再是个问题了,所以在较新的代码中装箱的频率就降低了。

    如果某些代码需要值类型,那么我们可以将int i传递给它,但是如果它需要引用类型,那么它可能对o中的5框不感兴趣。那么代码中何时显式地使用装箱转换呢?

    在练习中,拳击通常是自动发生的。如果希望让代码的读者更清楚地知道装箱正在发生,可以显式地装箱变量。如果性能可能是一个问题,这可能是相关的。

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

    因为 ToString 是上的虚拟方法 这意味着调用的实现依赖于运行时类型,而不是静态类型。自从 int 重写 托斯特林 它有自己的实现 int.ToString 调用,而不是由 对象 .

    object o = 5;
    Console.WriteLine(o.GetType());  // outputs System.Int32, not System.Object
    
        2
  •  0
  •   Jason Williams    14 年前

    1) 就其本身而言,意义不大。但是想象一下,你希望以一种通用的方式存储某个东西,而你不知道那个东西是一个值还是一个对象。通过装箱,您可以将值转换为对象,然后将所有内容都视为对象。但是,你需要一个特殊的箱子来保存一个值 一个物体。(这在列表之类的容器中最有用,允许您将5之类的值与对文件流之类的对象的引用混合在一起)。

    2) 装箱转换通常只隐式发生,除非在说明装箱的示例代码中。

    3) WriteLine代码可能调用virtual Object.ToString()方法。如果调用它的对象的类没有重写ToString,那么它将调用基类(对象)实现,但是大多数类型(包括System.Int尽管Int是值类型,但它仍然是从System.Object派生的)重写它以提供更有用的特定于上下文的结果。

        3
  •  0
  •   Fredrik Mörk    14 年前

    驻留在变量o中的5获得了哪些额外/有用的功能,而变量o所表示的5没有这些功能?

    装箱值类型没有获得额外的功能,除了它可以通过引用传递给需要它的代码。

    那么代码中何时显式地使用装箱转换呢?

    我不能自然而然地想到当你需要显式地 int 给一个 object ,因为在这个方向上总是有一个隐式转换(尽管如果有需要显式转换的情况,我也不会感到惊讶)。

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

    它叫 ToString 在传递的对象上。实际上,它首先尝试将对象转换为 IFormattable 内景 ToString overload that is defined in that interface . 这将返回“5”。

        4
  •  0
  •   Jeremy W. Sherman    14 年前

    附加功能:对象是一个成熟的对象。您可以调用它的方法并像使用任何其他对象一样使用它:

    System.Console.WriteLine("type: {0}", o.GetType());
    System.Console.WriteLine("hash code: {0}", o.GetHashCode());
    

    int变量是值类型,而不是对象。

    XXX号: 这是不正确的;请参阅注释。我敢说你用这两种方法的一个区别是 object o = 5 可以为空(您可以设置 o = null ),而值类型不是-if int i = 5 ,然后 i 总是一个整数。

    显式装箱:正如您所说,装箱版本是通过将操作对象编码为对象而不是整数来使用的。这就是启用非类型安全通用数据结构的原因。现在类型安全的通用数据结构已经可用,您不太可能进行大量的转换和装箱/拆箱操作。

    为什么是“5”:因为对象知道如何使用 ToString() .