using System; using SystemCollectionsGeneric; using SystemText; namespace TestString { class Program { static void Main(string[] args) { //在一次群组讨论中谈到了string的类型问题虽然它是引用类型却具有很多值类型的特点关于这个问题做了如下研究 //由于程序中可能存在大量的相同字符串为了节省内存C#应该是将下面两个变量都引用存放在同一个栈的test! string myString = test; string myString = myString; //那么按照引用的理论修改其中的一个字符串另一个就应该跟着改变例如做如下修改 myString = New test; ConsoleWriteLine(myString); //此时按理说myString应该也变成New test但事实上经过测试myString 还是 test这是为什么呢? //我分析微软应该是在string类型中引入了copyonwrite技术就是说我们在修改string类型变量的时候 //其实是重新开辟了一块内存将修改后的内容放进去 //再利用=把修改后的数据所在栈的地址传给被修改的字符串变量来达到修改字符串变量的目的! //下面的测试很好的说明了这个问题 myStringReplace(ta); ConsoleWriteLine(myString); //myStringReplace(ta);方法是把该字符串中的字母t换成字母a但是经过测试myString的内容依然是test //这就是因为虽然开辟了新空间并且将修改后的值存了进去 //但是没有用=将新数据栈的地址传给myString 所以myString的值没变! //与string类型相对应StringBuilder类型则有所不同 StringBuilder mySb = new StringBuilder(test); StringBuilder mySb = new StringBuilder(test); //StringBuilder类型在引用存放数据的栈之前加入了一个中间栈也就是说mySb指向它的中间栈 //假设这个中间栈叫stack然后stack再指向存放test的栈 //mySb也指向它的中间栈stack然后stack也指向存放test的那个栈当mySb被修改时 //依然是采用copyonwrite技术但是开辟新的栈并且把修改后的数据放进去后 //会自动修改stack让他重新指向新的数据栈而mySb一直还是指向中间栈stack //这样就实现了直接的修改而不用使用=来传递新地址给mySb看下面的测试 mySbReplace(ta); ConsoleWriteLine(mySb); //果然mySb被成功修改了! //Ps以上代码虽然有些警告但是可以运行主要是专注于说明问题忽略了一些细节比如赋值了的变量未使用等问题望见谅! } } } |