
C# 类与String(不是string)都是引用类型,存储在托管堆上,为什么下面的执行结果不同呢???
classModel{publicstringvalue{get;set;}}Modelobj1,obj2;obj1=newModel();obj1.value="A0"...
class Model
{
public string value { get; set; }
}
Model obj1, obj2;
obj1 = new Model();
obj1.value = "A0";
obj2 = obj1;
Console.WriteLine("obj1 is " + obj1.value);
Console.WriteLine("obj2 is " + obj2.value);
obj1.value = "another object";//断点检测obj2值也更改了
Console.WriteLine("obj1 is now " + obj1.value);
Console.WriteLine("obj2 is now " + obj2.value);
Console.WriteLine("------------------------------");
String str1 = "a string";
String str2 = str1;
Console.WriteLine("str1 is " + str1);
Console.WriteLine("str2 is " + str2);
str1 = "another string";//断点检测str2值没有更改
Console.WriteLine("str1 is now " + str1);
Console.WriteLine("str2 is now " + str2);
Console.ReadKey(); 展开
{
public string value { get; set; }
}
Model obj1, obj2;
obj1 = new Model();
obj1.value = "A0";
obj2 = obj1;
Console.WriteLine("obj1 is " + obj1.value);
Console.WriteLine("obj2 is " + obj2.value);
obj1.value = "another object";//断点检测obj2值也更改了
Console.WriteLine("obj1 is now " + obj1.value);
Console.WriteLine("obj2 is now " + obj2.value);
Console.WriteLine("------------------------------");
String str1 = "a string";
String str2 = str1;
Console.WriteLine("str1 is " + str1);
Console.WriteLine("str2 is " + str2);
str1 = "another string";//断点检测str2值没有更改
Console.WriteLine("str1 is now " + str1);
Console.WriteLine("str2 is now " + str2);
Console.ReadKey(); 展开
7个回答
展开全部
C#类实例是引用类型没错,所以第一部分的结果很好理解。
但是String是一个很特殊的类型,和普通引用类型不一样,是一种不可变类型。简单说,就是每个字符串都占据着一部分内存地址,并且它的值是不可改变的。当给String str1赋值的时候,它并没有改变原来str1指向的字符串的值,而是将str1指向了另一个字符串所在的位置。这次赋值之后,str1和str2所引用的对象已经不同了,查看它们的内存地址可以确认这一点。
但是String是一个很特殊的类型,和普通引用类型不一样,是一种不可变类型。简单说,就是每个字符串都占据着一部分内存地址,并且它的值是不可改变的。当给String str1赋值的时候,它并没有改变原来str1指向的字符串的值,而是将str1指向了另一个字符串所在的位置。这次赋值之后,str1和str2所引用的对象已经不同了,查看它们的内存地址可以确认这一点。
追问
原来是不可变类型,.C#本质论书上没说啊
再问一下
obj1 = new Model();
obj1.value = "A0";
obj1 = new Model();
这样obj1是覆盖原内存空间,还是重新创建内存空间?
追答
本质论上也许有提到过...
重新创建,原来的对象可能还没有被回收.
展开全部
Object是引用类型,String是值类型,当值类型复制的适合执行的是深度拷贝,会重新构造一个字符串,所以一个改变了,另一个不会改变,而引用类型复制的是指针,所以一个改变了,另一个也会改变.
追问
瞎吹吧String是值类型
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
纠正几点楼主认识上的错误~~
1.C#中的 string 其实就是 System.String 类型的别名,即 using string = System.String,两者没有任何区别。
2.你的程序不能说明引用类型或者值类型的问题。
第一个程序,obj1 是 Model 类型的一个实例,而 Model 是引用类型,所以,当你 obj2 = obj1 时,obj2和obj1就指向了同一个对象。因此,它们的成员相等也就不足为奇了。而这和它的成员 value 并没有关系,即使它是int(即System.Int32,值类型)也没有关系。
3.第二个程序,String str2 = str1;让 str2 和 str1 指向了同一个字符串,这是没错的,因为string是引用类型。可是string的值是不可变的,当你str1 = "another string";时,str1就指向了新的字符串,而str2还是指向原来的字符串,因此就产生了你说的那种结果。
因此你的第二个程序就相当于(用你的Model类来说明):
Model m1 = new Model();
m1.value = "a string";
Model m2 = m1;
Console.WriteLine("str1 is " + m1.value);
Console.WriteLine("str2 is " + m2.value);
m1 = new Model();
m1.value = "another object";
Console.WriteLine("str1 now is " + m1.value);
Console.WriteLine("str2 now is " + m2.value);
很明显,它们的结果不同。
============补充
汗了,打了这么多字,已经有这么多人回答了。
如果想检查两个引用是否指向同一个对象。可以调用
object.ReferenceEquals() 静态方法来判断
1.C#中的 string 其实就是 System.String 类型的别名,即 using string = System.String,两者没有任何区别。
2.你的程序不能说明引用类型或者值类型的问题。
第一个程序,obj1 是 Model 类型的一个实例,而 Model 是引用类型,所以,当你 obj2 = obj1 时,obj2和obj1就指向了同一个对象。因此,它们的成员相等也就不足为奇了。而这和它的成员 value 并没有关系,即使它是int(即System.Int32,值类型)也没有关系。
3.第二个程序,String str2 = str1;让 str2 和 str1 指向了同一个字符串,这是没错的,因为string是引用类型。可是string的值是不可变的,当你str1 = "another string";时,str1就指向了新的字符串,而str2还是指向原来的字符串,因此就产生了你说的那种结果。
因此你的第二个程序就相当于(用你的Model类来说明):
Model m1 = new Model();
m1.value = "a string";
Model m2 = m1;
Console.WriteLine("str1 is " + m1.value);
Console.WriteLine("str2 is " + m2.value);
m1 = new Model();
m1.value = "another object";
Console.WriteLine("str1 now is " + m1.value);
Console.WriteLine("str2 now is " + m2.value);
很明显,它们的结果不同。
============补充
汗了,打了这么多字,已经有这么多人回答了。
如果想检查两个引用是否指向同一个对象。可以调用
object.ReferenceEquals() 静态方法来判断
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
其实我觉得你上面的比较不能完全等效。
第一个例子中是改变了Model中的一个属性,因此obj1和obj2还是指向同一个Model引用。
而第二个例子你是直接改变了str1的字符串引用。因此str1和str2已经指向了不同的子符串引用了。
假如你的第一个例子里面改为以下形式你也会发现和第二个例子一样:
obj1 = new Model();
obj1.value = "A0";
obj2 = obj1;
Console.WriteLine("obj1 is " + obj1.value);
Console.WriteLine("obj2 is " + obj2.value);
obj1 = new Model();
Console.WriteLine("obj1 is now " + obj1.value);
Console.WriteLine("obj2 is now " + obj2.value);
这样的做法才和第二个例子一样情况。
第一个例子中是改变了Model中的一个属性,因此obj1和obj2还是指向同一个Model引用。
而第二个例子你是直接改变了str1的字符串引用。因此str1和str2已经指向了不同的子符串引用了。
假如你的第一个例子里面改为以下形式你也会发现和第二个例子一样:
obj1 = new Model();
obj1.value = "A0";
obj2 = obj1;
Console.WriteLine("obj1 is " + obj1.value);
Console.WriteLine("obj2 is " + obj2.value);
obj1 = new Model();
Console.WriteLine("obj1 is now " + obj1.value);
Console.WriteLine("obj2 is now " + obj2.value);
这样的做法才和第二个例子一样情况。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
前面一段代码操作的是Model类(一个派生于Object的普通类),obj1,obj2两个引用所指向的空间是同一个,所以其中一个的数据更新了,也会影响到另一个,一定要注意,obj1和obj2指向了同一个对象,堆上只有一份string类型的数据
后一段代码str1申明并初始化了一个String类型的对象(其实C#会自动把string转换成String),
然后str2又声明了一个String类型的引用,并把它指向str1
但是C#在处理String的时候比较特殊,它并不像普通的类型一样在引用被重用的时候重用真实数据,其实C#在处理str2=str1这句语句的时候,会隐式的new一个String对象,然后把str1的值拷贝到这个新对象中,然后让str2指向这个新对象
就像Int32(int) ,Int64(long)这些一样,在C#里面,int会被看作Int32,long会被看作Int64(其实,C#里面可以认为没有基础数据类型,只有派生于Object的类) ,如下这样的代码也会产生两个互相独立的int对象:
int a=1;
int b=a;
b=2;
Console.WriteLine(a.ToString()+b.ToString());//会显示"12"
类似的处理string的机制也出现在java等语言中
后一段代码str1申明并初始化了一个String类型的对象(其实C#会自动把string转换成String),
然后str2又声明了一个String类型的引用,并把它指向str1
但是C#在处理String的时候比较特殊,它并不像普通的类型一样在引用被重用的时候重用真实数据,其实C#在处理str2=str1这句语句的时候,会隐式的new一个String对象,然后把str1的值拷贝到这个新对象中,然后让str2指向这个新对象
就像Int32(int) ,Int64(long)这些一样,在C#里面,int会被看作Int32,long会被看作Int64(其实,C#里面可以认为没有基础数据类型,只有派生于Object的类) ,如下这样的代码也会产生两个互相独立的int对象:
int a=1;
int b=a;
b=2;
Console.WriteLine(a.ToString()+b.ToString());//会显示"12"
类似的处理string的机制也出现在java等语言中
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
2楼回答的基本上是正确的,string是引用但是一种不可变的引用,当str2=str1的时候其实已经另外创建了一个对象并且将str1指向地址的值赋值给str2了,所以改变str1不会改变str2的值
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询