System.String是不可变的字符串吗?

本文探讨了.NET编程中System.String类的不可变特性,并通过C++/CLI示例展示了如何绕过限制直接修改字符串内容。揭示了StringInterning机制下此操作的风险。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在学习.net编程时,你一定有听到过这样的说法,System.String类是不可变字符串,也就是说你不能修改一个字符串的值。

比如以下这段代码

None.gifstring s = "hello";
None.gif
= "world";

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

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

None.gifstring s1 = "hello";
None.gif
string s2 = "hello";
None.gif
None.gif
if (Object.ReferenceEquals(s1, s2))
None.gif                Console.WriteLine(
"They are same");

s1和s2其实指向相同的字符串。

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

None.gif    String^ s1 = "hello";
None.gif    String
^ s2 = "hello";
None.gif
None.gif    interior_ptr
<Char> p = const_cast<interior_ptr<Char> >(PtrToStringChars(s1));
None.gif
None.gif    
for(; *p; *p++='a');            
None.gif
None.gif    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搞掉!emsmilep.gif

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

当然,以上例子只是说明存在修改string实例的内容的可能,并不是鼓励大家这么做。虽然直接访问string实例内部的字符串,可能会带来一些性能上的好处。但是由于String Interning的存在,修改String实例内部的字符串是相当危险的行为,比如上面的那个例子中,你会发现,s1的输出也变成aaaaa了!emdgust.gif

转载于:https://www.cnblogs.com/Hush/archive/2004/12/07/74098.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值