C# 奇怪的值类型方法调用
创建一个 Point 类型,拥有 x 和 y 两个私有变量,一个 Change 方法改变 xy 的值,一个重写的 ToString 方法.
csharp
using System;
namespace StructSample
{
class Program
{
static void Main(string args)
{
Point p1 = new Point(1, 1);
Console.WriteLine(p1); // ( 1, 1 )
p1.Change(2, 2);
Console.WriteLine(p1); // ( 2, 2 )
Object o = p1;
Console.WriteLine(o); // ( 2, 2 )
((Point)o).Change(3, 3);
Console.WriteLine(o); // ( 2, 2 )
Console.ReadLine();
}
}
struct Point
{
private int m_x, m_y;
public Point(int x, int y)
{
m_x = x;
m_y = y;
}
public void Change(int x, int y)
{
m_x = x;
m_y = y;
}
public override string ToString()
{
return String.Format("( {0}, {1} )", m_x, m_y);
}
}
}前面 3 次的输出都很正常,第四次输出跟预想的就不一样了,虽然调用了 Change(3, 3),但输出仍为 ( 2, 2 ) 。
原因还在于值类型的装箱和拆箱。看一下第二次调用 Change 的代码:
csharp
((Point)o).Change(3, 3);因为 Object 类型没有 Change 方法,所以 o 必须显示转换为 Point 型才能调用 Change 方法。
这里会发生一次拆箱,将 o 拆箱后放入栈中,然后调用 Change 方法改变栈中的值,执行结束后栈中的值变为 ( 3, 3) 。
Change 方法结束后,栈中的值并不会再次装箱,而且该值也不会再被引用到,会立即被系统回收。
堆中 o 变量引用的值由于没有发生变更,所以打印的结果仍然为 ( 2, 2) 。