两个变量的ToString调用之间有什么区别?
int i = 0;
i.ToString();
在调用ToString()之前,调用i.ToString()是否会使我首先装箱然后调用ToString或者我已装箱?
答案 0 :(得分:4)
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();
}
}
}
被翻译为:
.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()
被调用。
如果举行拳击比赛,您明确或隐含地将int
投放到object
。 (请注意,转换为object
类型不是拳击发生的唯一情况)
显式转换为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
通过隐式演员进行拳击:
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()`。
这是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
答案 1 :(得分:0)
技术上,int继承自System.ValueType,该实体继承自object。但要回答你的问题,没有性能损失。所有价值类型都是密封类型,它们既不是派生的,也不是派生的。因此,虽然正如哈姆雷特哈博伊恩所指出的那样,ToString被int覆盖,它被有效地封存,并且没有虚拟调度,这将需要执行拳击。