您的位置:首页 > 职场人生

一道面试题:解析方法中对象存放以及堆栈之间的关系

2011-03-20 01:36 393 查看
朋友面试遇到一道题是这样的:

namespace Demo
{

internal class Program
{
private static void Main()
{
Person p=new Person("alex");
Upate(p);
Console.WriteLine(p.ToString());
Console.Read();
}
static void Upate(Person p)
{
p=new Person("franck");
}
}

internal class Person
{
private string _name;
public Person(string name)
{
this._name=name;
}

public override string ToString()
{
return this._name;
}
}
}
1,输出的结果是?

2,分析其执行过程

答案是输出结果是:alex

为什么会这样呢,这才是问题所在。好多人会认为在、执行Update方法时对象p发生了改变,事实也是这样的,但为什么结果没有变化,要分析清楚原因,还得看IL

entrypoint
// Code size 38 (0x26)
.maxstack 2
.locals init ([0] class Demo.Person p)
IL_0000: nop
IL_0001: ldstr "alex"
IL_0006: newobj instance void Demo.Person::.ctor(string)
IL_000b: stloc.0 //从计算堆栈的顶部弹出当前值并将其存储到索引 0 处的局部变量列表中
IL_000c: ldloc.0 //将索引 0 处的局部变量加载到计算堆栈上
IL_000d: call void Demo.Program::Upate(class Demo.Person)
IL_0012: nop
IL_0013: ldloc.0 //将索引 0 处的局部变量加载到计算堆栈上
IL_0014: callvirt instance string [mscorlib]System.Object::ToString()
IL_0019: call void [mscorlib]System.Console::WriteLine(string)
IL_001e: nop
IL_001f: call int32 [mscorlib]System.Console::Read()

Upate Method
.method private hidebysig static void Upate(class Demo.Person p) cil managed
{
// Code size 14 (0xe)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "franck"
IL_0006: newobj instance void Demo.Person::.ctor(string)
IL_000b: starg.s p //将位于计算堆栈顶部的值存储在参数槽中的指定索引处
IL_000d: ret //从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。
} // end of method Program::Upate

这是所有执行的IL吗,根据我做的注释,这一下应清楚了,事实上Update方法执行是在另一个堆栈上,这个堆栈上的执行结果在没有推送到调用方堆栈,在Main()方法的堆栈中,p对象还是原来的对象。

图示:

Main()

Person p=new Person("alex");

Upate 方法同样会产生一个这样的堆栈,方式和上面相同。关键就在这一句上了

IL_000d: ret //从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。

当Update堆栈上的对象没有推送到Main()产生的堆栈上的时间,图1堆栈中存放的对象p不变,因而输出结果就是那样!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐