ValueType.ToString和ReferenceType.ToString之间的区别 [英] difference between ValueType.ToString and ReferenceType.ToString

查看:44
本文介绍了ValueType.ToString和ReferenceType.ToString之间的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

两个变量的ToString调用之间有什么区别?

What is the difference between two variable's ToString Calling ?

int i = 0;
i.ToString();

调用i.ToString()会使我先被装箱,然后调用ToString还是在调用ToString()之前已经被装箱了?

Does calling i.ToString() will make i first boxed then call ToString or i is already boxed before calling ToString() ?

推荐答案

int System.Int32 结构类型(隐式密封)的别名,该结构类型具有方法 Int32.ToString(),这是在代码第二行中调用的方法,因此不会发生类型转换.

int is an alias of System.Int32 struct type (implicitly sealed) which has a method Int32.ToString() and this is a method called in the second line of your code so no type conversion occurs.

System.Int32 是从 System.ValueType 派生的,而 System.ValueType 是从 System.Object 派生的. Int32.ToString()覆盖 ValueType.ToString(),后者覆盖 Object.ToString().

System.Int32 is derived from System.ValueType which is derived from System.Object. Int32.ToString() overrides ValueType.ToString() which overrides Object.ToString().

检查拳击是否发生的最好方法是查看IL代码(我一直在使用ILSpy):

The best way to check whether boxing occurs is to see IL code (I've been using ILSpy):

using System;

namespace BoxingTest
{
    class Program
    {
        static void Main(string[] args)
        {
            int i = 0;
            string s1 = i.ToString();
        }
    }
}

被翻译为:

.method private hidebysig static 
    void Main (
        string[] args
    ) cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 12 (0xc)
    .maxstack 1
    .entrypoint
    .locals init (
        [0] int32 i,
        [1] string s1
    )

    IL_0000: nop
    IL_0001: ldc.i4.0
    IL_0002: stloc.0
    IL_0003: ldloca.s i
    IL_0005: call instance string [mscorlib]System.Int32::ToString()
    IL_000a: stloc.1
    IL_000b: ret
} // end of method Program::Main

您可以看到没有装箱,并且调用了 System.Int32 :: ToString().

You can see that no boxing occurred and that System.Int32::ToString() was called.

如果例如您将您的 int 显式或隐式转换为 object .(请注意,装箱不是唯一的情况是转换为 object 类型)

Boxing would have taken place if e.g. you casted your int to object explicitly or implicitly. (Note that conversion to object type is not the only case when boxing happens)

显式强制转换以键入 object :

using System;

namespace BoxingTest
{
    class Program
    {
        static void Main(string[] args)
        {
            int i = 0;
            string s2 = ((object)i).ToString();
        }
    }
}

给予:

.method private hidebysig static 
    void Main (
        string[] args
    ) cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 16 (0x10)
    .maxstack 1
    .entrypoint
    .locals init (
        [0] int32 i,
        [1] string s2
    )

    IL_0000: nop
    IL_0001: ldc.i4.0
    IL_0002: stloc.0
    IL_0003: ldloc.0
    IL_0004: box [mscorlib]System.Int32
    IL_0009: callvirt instance string [mscorlib]System.Object::ToString()
    IL_000e: stloc.1
    IL_000f: ret
} // end of method Program::Main

通过隐式转换进行装箱:

Boxing through implicit cast:

using System;

namespace BoxingTest
{
    class Program
    {
        static void Main(string[] args)
        {
            int i = 0;
            object o = i;
            string s3 = o.ToString();
        }
    }
}

给予:

.method private hidebysig static 
    void Main (
        string[] args
    ) cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 18 (0x12)
    .maxstack 1
    .entrypoint
    .locals init (
        [0] int32 i,
        [1] object o,
        [2] string s3
    )

    IL_0000: nop
    IL_0001: ldc.i4.0
    IL_0002: stloc.0
    IL_0003: ldloc.0
    IL_0004: box [mscorlib]System.Int32
    IL_0009: stloc.1
    IL_000a: ldloc.1
    IL_000b: callvirt instance string [mscorlib]System.Object::ToString()
    IL_0010: stloc.2
    IL_0011: ret
} // end of method Program::Main

在所有三种情况下,字符串将具有值"0" ,因为 Object.ToString()知道装箱变量的原始类型并调用该变量的ToString()`.类型.

In all three cases strings will have value "0" because Object.ToString() knows the original type of the boxed variable and calls ToString()` of that type.

这是 Object.ToString()的IL代码:

.method public hidebysig newslot virtual 
    instance string ToString () cil managed 
{
    .custom instance void __DynamicallyInvokableAttribute::.ctor() = (
        01 00 00 00
    )
    // Method begins at RVA 0x2052
    // Code size 12 (0xc)
    .maxstack 8

    IL_0000: ldarg.0
    IL_0001: call instance class System.Type System.Object::GetType()
    IL_0006: callvirt instance string System.Object::ToString()
    IL_000b: ret
} // end of method Object::ToString

这篇关于ValueType.ToString和ReferenceType.ToString之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆