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

捷哥1999 2009-02-03 09:53:34
string text="simple string";
text="other string";
这个时候text已经不是原来的text了,谁能讲解得透彻一些?
...全文
209 16 打赏 收藏 转发到动态 举报
AI 作业
写回复
用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".
在Windows 10或Windows 11操作系统中,用户经常会遇到共享打印机时出现的一系列错误代码,这些错误代码可能会阻碍打印机共享功能的正常使用。常见的错误代码包括0x00000057、0x00000709和0x0000011b,这些代码通常指出了不同的问题,比如权限不足、服务未运行或配置错误等。除此之外,还有一些故障提示如“连接失败”或“内存不足”,这些都可能影响到打印机共享的稳定性。 要解决这些故障,首先要确保打印机已经正确地连接到网络,并且在需要共享的电脑上进行了设置。确保打印机驱动程序是最新的,并且在共享设置中没有错误配置。对于权限问题,需要检查网络上的用户账户是否具有足够的权限来访问共享打印机。同时,也要确保打印机服务正在运行,特别是“Print Spooler”服务,因为这是打印机共享服务的核心组件。 在某些情况下,问题可能与操作系统的更新有关,如升级到最新版的Windows 10或Windows 11后可能出现的兼容性问题。这时,可能需要查看微软的官方支持文档来获取特定的解决方案或更新。 对于错误代码0x00000057,这通常是由于没有足够的权限来访问网络打印机或其共享资源,解决方法是确保网络打印机的权限设置正确,包括在组策略中设置相应的访问权限。而0x00000709错误可能是由于打印机驱动问题或打印机端口配置错误,可以尝试重新安装或更新打印机驱动来解决。至于0x0000011b错误,这往往是因为打印机队列服务的问题,检查并重启“Print Spooler”服务通常是解决这类问题的常见手段。 至于“连接失败”或“内存不足”这类故障,通常与客户端和打印机之间的网络连接以及打印机本地资源的使用情况有关。检查网络连接,确保打印机所在的网络段没有故障或中断。同时,如果打印机的打印队列长时间得不到处理,可能会导致内存不足的情况,这时可能需要清理打印队列或增加打印机的内存配置。 为了帮助用户更快速地解决这些问题,市面上出现了各种打印机共享错误修复工具。这些工具往往通过预设的修复程序来自动检测和修正打印机共享中常见的问题。它们可以快速检查打印机驱动、网络连接以及共享设置,并且能够提供一键修复功能,大幅减少了用户自行排查和解决问题的难度。 然而,在使用这些修复工具之前,用户应确保这些工具的来源是安全可靠的,避免因使用不当的修复工具而引发其他系统安全或隐私问题。用户可以到官方平台或者信誉良好的软件提供商处下载这些工具。通过细心检查打印机的共享设置,及时更新驱动程序和服务,以及合理使用修复工具,大多数共享打印机的问题都可以得到有效的解决。

111,098

社区成员

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

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

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