我们都知道stringg类型变量,其值是不可变的,那么如何解释下面的代码,不要简单的道理讲解,要代码层面上的解释,谢谢高手!

捷哥1999 2009-02-03 09:53:34
string text="simple string";
text="other string";
这个时候text已经不是原来的text了,谁能讲解得透彻一些?
...全文
186 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
bluedodo 2009-02-04
  • 打赏
  • 举报
回复
你的内存里有两个字符串,text的指向变了
accomp 2009-02-04
  • 打赏
  • 举报
回复
说白了就是指向变了
原来的 simple string 还在内存中 。

不像 StringBuilder 直接在原地址改内容
sxmonsy 2009-02-04
  • 打赏
  • 举报
回复
LZ你要干嘛?
HDNGO 2009-02-04
  • 打赏
  • 举报
回复
c#一直觉得比较混乱的一个关于string的东西是string留用~


static void Main(string[] args)
{
string x = "should it matter";
string y = "should it matter";
if (object.ReferenceEquals(x, y))
{
Console.WriteLine("same reference.");
}
Console.Read();
}
程序运行的结果是输出了“same reference.”,照理说我声明两个string变量,它们不应该指向相同的托管堆地址啊?!事实上这里涉及到一个所谓的“字符串留用”机制,根据Jeffrey Richter在《框架设计:CLR via C#》中所说,CLR存在一种机制,当它初始化时,它会创建一个内部哈希表,此表中key是字符串,value是对托管堆中的string对象的引用。当定义一个string 时,就会在内部哈希表中检查是否有相匹配的。如果不存在完全相同的字符串,就创建字符串副本,将字符串副本添加到内部哈希表中,并返回这个副本的引用。如果存在完全相同的字符串,就返回对现有字符串的引用。


这么做。。。难道是为了内存效率??够混乱的。。。。


HDNGO 2009-02-04
  • 打赏
  • 举报
回复
string的这一特性是指,对于已有的一个string对象,当你修改它时,实际是重新创建了一个符合你要求的string对象。我通过以下的例子进行演示:
static void Main(string[] args)
{
string x = "should it matter";
x = x + " ?"; //breakpoint (1)
}//breakpoint (2)


F5运行至breakpoint (1)处,在即时窗口中执行以下sos调试命令(关于sos调试扩展,可以参见《VS 2005中Sos调试扩展简介》):

!load sos.dll
extension C:"WINDOWS"Microsoft.NET"Framework"v2.0.50727"sos.dll loaded
!clrstack -a
PDB symbol for mscorwks.dll not loaded
OS Thread Id: 0x1508 (5384)
ESP EIP
0012f440 012f009f ConsoleApplication1.Program.Main(System.String[])
PARAMETERS:
args = 0x0137cdc8
LOCALS:
<CLR reg> = 0x0137cdd8
0012f69c 79e7c74b [GCFrame: 0012f69c]


又F5运行至breakpoint (2)处,重新执行clrstack命令,结果如下。可清楚看到对象x在内存中的地址发生了变化,由原来的0x0137cdd8变成0x0137ce24。

!clrstack -a
OS Thread Id: 0x1508 (5384)
ESP EIP
0012f440 012f00b0 ConsoleApplication1.Program.Main(System.String[])
PARAMETERS:
args = 0x0137cdc8
LOCALS:
<CLR reg> = 0x0137ce24
0012f69c 79e7c74b [GCFrame: 0012f69c]


转自:http://www.cnblogs.com/KissKnife/archive/2008/10/25/1319352.html
流年岁月 2009-02-04
  • 打赏
  • 举报
回复
呵呵,帮顶了
jlj84237485 2009-02-04
  • 打赏
  • 举报
回复
帮顶一下
wuyi8808 2009-02-04
  • 打赏
  • 举报
回复
string text = "simple string"; 
text = "other string";

两个字符串的值都没变,是 text 变了。

text --> "simple string"

变成:

没有指向 --> "simple string"
text --> "other string"
Wesley 2009-02-04
  • 打赏
  • 举报
回复
我也跟着学习了
宝_爸 2009-02-04
  • 打赏
  • 举报
回复
我晕,这么厉害。
官方说法来了:

Immutability of String Objects
String objects are immutable: they cannot be changed after they have been created. All of the String methods and C# operators that appear to modify a string actually return the results in a new string object. In the following example, when the contents of s1 and s2 are concatenated to form a single string, the two original strings are unmodified. The += operator creates a new string that contains the combined contents. That new object is assigned to the variable s1, and the original object that was assigned to s1 is released for garbage collection because no other variable holds a reference to it.

C# Copy Code
string s1 = "A string is more ";
string s2 = "than the sum of its chars.";

// Concatenate s1 and s2. This actually creates a new
// string object and stores it in s1, releasing the
// reference to the original object.
s1 += s2;

System.Console.WriteLine(s1);
// Output: A string is more than the sum of its chars.



Because a string "modification" is actually a new string creation, you must use caution when you create references to strings. If you create a reference to a string, and then "modify" the original string, the reference will continue to point to the original object instead of the new object that was created when the string was modified. The following code illustrates this behavior:

C# Copy Code
string s1 = "Hello ";
string s2 = s1;
s1 += "World";

System.Console.WriteLine(s2);
//Output: Hello


For more information about how to create new strings that are based on modifications such as search and replace operations on the original string, see How to: Modify String Contents (C# Programming Guide).


摘自:
String Basics (C# Programming Guide)
http://msdn.microsoft.com/en-us/library/ms228362.aspx
nevana 2009-02-04
  • 打赏
  • 举报
回复
简单的讲,当string text="simple string"时,此时text对应了一个内存地址001,地址中存放的值是"simple string",在不改变地址的情况下text对应的值是不能改变的。当第二句text="other string";执行后,此时text对应了一个新的内存地址002,这时就是一个全新的text值了,刚才001号text已经死了。如果换成stringbuffer类就不一样了,可以为001号stringbuffer text再增加或减少字符的。
renzaijiang 2009-02-03
  • 打赏
  • 举报
回复
在学习.net编程时,你一定有听到过这样的说法,System.String类是不可变字符串,也就是说你不能修改一个字符串的值。

比如以下这段代码

string s = "hello";
s = "world";
你并不是把s的值修改为world,而是生成了一个新的包含"world"的字符串,然后令s这个字符串的引用指向新的字符串,而原来的那个字符串就被抛弃掉了。

也正是基于String类的不可修改性,CLR采用了String Interning的技术来共享相同的字符串,以达到减少内存使用的目的。比如以下这段代码

string s1 = "hello";
string s2 = "hello";

if (Object.ReferenceEquals(s1, s2))
Console.WriteLine("They are same");
s1和s2其实指向相同的字符串。

那么是不是我们真的没有办法改变一个string的值呢?当然不是,在C++/CLI中,我们可以使用一些特殊的手段来达到我们的目的!

String^ s1 = "hello";
String^ s2 = "hello";

interior_ptr<Char> p = const_cast<interior_ptr<Char> >(PtrToStringChars(s1));

for(; *p; *p++='a');

Console::WriteLine("{0} and {1}",s1,s2);



PtrToStringChars(String^)是一个定义在vcclr.h头文件中的一个helper function,它返回一个类型为interior_ptr<const Char>的内部指针,指向String实例内部所包含的字符串,之所以返回类型是interior_ptr<const Char>而不是interior_ptr<Char>是因为不希望我们改变String实例内的字符串,不过既然我们执意要这么做,那么就让我们用一个const_cast<T>来把这个const搞掉!

运行以上代码你会发现,s2现在的内容已经是aaaaa,而不是hello了。

当然,以上例子只是说明存在修改string实例的内容的可能,并不是鼓励大家这么做。虽然直接访问string实例内部的字符串,可能会带来一些性能上的好处。但是由于String Interning的存在,修改String实例内部的字符串是相当危险的行为,比如上面的那个例子中,你会发现,s1的输出也变成aaaaa了!
我姓区不姓区 2009-02-03
  • 打赏
  • 举报
回复
对于string这个引用类型是非常特殊一个引用类型。
它有两点特殊的地方。
第一点对象分配的特殊。
例如
string str1 = "abcd";
string str2 = "abcd";
那么.net在分配string类型的时候,先查看当前string类型列表是否有相同的,如果有的话,直接返回其的引用,否则重新分配。

第二点对象引用操作的特殊,可以说不同于真正意义上的引用操作。
例如:
string str1 = "abcd";
string str2 = str1;
str2 = "efgh";// str1 is still "abcd" here
当对于一个新的string类型是原有对象引用的时候,这点和一般的引用类型一样,但是当新的对象发生变化的时候,要重新分配一个新的地方,然后修改对象指向。

因此对于string操作的时候,尤其发生变化的时候,会显得比较慢,因为其牵扯到内存地址的变化。
对于数据量比较大的字符操作时候,使用StringBuilder来说效率会提升很高。
Fibona 2009-02-03
  • 打赏
  • 举报
回复
对于string类型,虽然是引用类型,但每次附值或者字符串相加都是重新实例化一个新的字符串实例,并且附新的值给该字符串变量

vrhero 2009-02-03
  • 打赏
  • 举报
回复
这个时候text已经不是原来的text了
----------
错了...简单的说,这个时侯text对象还是那个引用,但这个引用指向的地址已经改变了...
Akron 2009-02-03
  • 打赏
  • 举报
回复
两个字符串都没变,变的是 text 变量本身,确切的说是 string 内部的地址,也就是指针。这个指针现在指向了新的string "other string".

110,539

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧