两个变量的ToString调用有什么区别?
int i = 0;
i.ToString();
Run Code Online (Sandbox Code Playgroud)
在调用ToString()之前,调用i.ToString()会使我首先装箱然后调用ToString或者我已经装箱了吗?
int是结构类型的别名System.Int32(隐式密封),它有一个方法Int32.ToString(),并且这是在代码的第二行中调用的方法,因此不会发生类型转换。
System.Int32源自 源自System.ValueType源自System.Object。Int32.ToString()覆盖ValueType.ToString()哪个覆盖Object.ToString().
检查是否发生装箱的最好方法是查看IL代码(我一直在使用ILSpy):
using System;
namespace BoxingTest
{
class Program
{
static void Main(string[] args)
{
int i = 0;
string s1 = i.ToString();
}
}
}
Run Code Online (Sandbox Code Playgroud)
翻译为:
.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
Run Code Online (Sandbox Code Playgroud)
您可以看到没有发生拳击并且System.Int32::ToString()被判罚了。
如果你把你的投掷int到object。(请注意,转换为object类型并不是装箱发生的唯一情况)
显式转换为类型object:
using System;
namespace BoxingTest
{
class Program
{
static void Main(string[] args)
{
int i = 0;
string s2 = ((object)i).ToString();
}
}
}
Run Code Online (Sandbox Code Playgroud)
给出:
.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
Run Code Online (Sandbox Code Playgroud)
通过隐式强制转换进行拳击:
using System;
namespace BoxingTest
{
class Program
{
static void Main(string[] args)
{
int i = 0;
object o = i;
string s3 = o.ToString();
}
}
}
Run Code Online (Sandbox Code Playgroud)
给出:
.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
Run Code Online (Sandbox Code Playgroud)
在所有三种情况下,字符串都有价值"0",因为Object.ToString()知道装箱变量的原始类型并调用该类型的 ToString()`。
这是以下的 IL 代码Object.ToString():
.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
Run Code Online (Sandbox Code Playgroud)