2009-11-17

值类型和引用类型

最初的理解:值类型传递值,引用类型传递引用,对于引用类型,加不加ref关键字是没有区别的

值类型,传递值:
static void Main(string[] args)
{
int x = 7;
Console.WriteLine(x.ToString());
Change(x);
Console.WriteLine(x.ToString());
Console.ReadLine();
}

private static void Change(int x)
{
x = 8;
}

Change 方法不会改变x的值,输出为:
7
7

引用类型传递引用:

class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
mc.x = 7;
Console.WriteLine(mc.x.ToString());
Change(mc);
Console.WriteLine(mc.x.ToString());

Console.ReadLine();
}

static void Change(MyClass mc)
{
mc.x = 6;
}
}

class MyClass
{
public int x;
}

输出为:
7
6

但是下面的输出什么呢?

static void Main(string[] args)
{
string x = "hello";
Console.WriteLine(x);
Change(x);
Console.WriteLine(x);

Console.ReadLine();
}

static void Change(string x)
{
x = "world";
}

答案是:都是hello。此例经常被用作面试题。string是引用类型无疑,方法传递的也是引用,但是x的值却没有改变,此例经常用来说明string类型的特殊性,不可变性,真的是这样么?下面的程序片段又输出什么?

static void Main(string[] args)
{
MyClass mc = new MyClass();
mc.x = 6;
Console.WriteLine(mc.x.ToString());
Change(mc);
Console.WriteLine(mc.x);

Console.ReadLine();
}

static void Change(MyClass y)
{
y = new MyClass();
y.x = 7;
}

答案是:
6
6

这个例子和上面的例子本质上是一样的,都是传递的引用的内容,方法只是改变了引用本身(地址),使其指向了新对象的地址,接下来的改变都是在新对象上进行的,也就无法返回到原来的对象,但是如果我们加上ref

MyClass mc = new MyClass();
mc.x = 6;
Console.WriteLine(mc.x.ToString());
Change(ref mc);
Console.WriteLine(mc.x);

Console.ReadLine();
}

static void Change(ref MyClass y)
{
y = new MyClass();
y.x = 7;
}

输出就变成了:
6
7

此处,我们传递的的是引用的引用,也就是引用的地址,可以改变引用本身,也可以改变原对象

参考:

http://www.cnblogs.com/anytao/archive/2007/05/28/must_net_09.html
http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory2B01142006125918PM/csharp_memory2B.aspx
http://msdn.microsoft.com/zh-cn/library/14akc2c7(VS.80).aspx

No comments: