提问:
class Class1
{
static void StrChange(string str)
{
str = "hellow";
}
static void Main()
{
string str = "123";//申明一个字符串
StrChange(str);//调用方法
Console.WriteLine(str);//输出字符串
}
}
输出的结果是 "123"
string 到底是值类型还是引用类型?
如果是值类型,结果倒还说的过去.但是我记得string 是引用类型啊...难道是我记错了??
如果是引用类型的话.输出的结果应该是: "hellow"
请问这是为什么啊?? 大家帮忙解释一下..谢谢
问题补充:class Program
{
//引用类型
class SomeRef
{
public int x;
}
//值类型
struct SomeVal
{
public int x;
}
private static void ChangeRef(SomeRef r)
{
r.x = 555;
}
private static void ChangeVal(SomeVal v)
{
v.x = 5556;
}
static void Main(string[] args)
{
SomeRef r1 = new SomeRef();//分配在托管堆上
SomeVal v1 = new SomeVal();
r1.x = 5;//解析指针
v1.x = 5;
ChangeRef(r1);
ChangeVal(v1);
Console.WriteLine(r1.x);
Console.WriteLine(v1.x);
}
}
回答:
String是引用类型,这是不用质疑的,但是String引用的对象非常特殊。
C#为了减少字符串的内存占用,采取了这样的策略,相同的字符串使用相同的内存空间,比如string a = "123"和string b = "123",虽然是两个string,但它们指向同一个内存地址。
请注意string由此带来的特殊性,假如此刻给a重新赋值:a = "456",原先那个内存地址中存放的依旧是"123"这是无法修改的,所以只能修改a的内存指向。
现在我们来看方法传值,普通的Object o传递进方法Me(Object o),真正的过程是,先新建一个新的变量o1(假设是这个名字),然后把o的引用地址复制给o1,现在o和o1引用相同的对象。现在在方法中修改o1.Name = "新名字",修改的是被o和o1共同引用的对象,因此o.Name自然也会变成新名字。
再看String,string s = "旧名字",传递进Me(string s),真正的过程是,先新建一个新的变量s1,然后把s的引用地址复制给s1,现在s和s1引用相同的字符串内存地址。方法中修改s1="新名字",由于原先的内存中的"旧名字"无法修改成"新名字",所以就需要新建一个内存空间存"新名字",然后将新的地址给s1,所以这时s和s1已经引用的不是同一个地址了!所以s和s1才会不相同。
请注意,这个机制很特殊,它既不是普通的对象那样,也和按值传递不同,按值传递是将整个值传了一个拷贝进去,因此无论怎么修改也两不干扰。
写的尽可能通俗易懂了,尽可能白话了,应该理解了吧?
补充:没搞懂你问题补充是为了说明什么…… SomeRef会被初始化在堆上,SomeVal会被初始化在栈上,ChangeRef时,形参r会获得和r1相同的地址引用,ChangeVal时,形参v会获得v1的一个完整的拷贝,然后再被放在栈的一个新区域去。所以,r1被传进ChangeRef之后,r的改变即为r1的改变,而v1被传递进ChangeVal之后,其实传递的是一个完整的包含值的拷贝,此时v与v1已经没有任何关系。所以之后r1被修改了,而v1没有改变。正好印证了我的以上说法。-- Coki 1天前
应该说是和string是有差别的。
本文解析了C#中字符串作为引用类型的特殊行为,并通过实例对比了引用类型与值类型的差异。
3256

被折叠的 条评论
为什么被折叠?



