string 是一个比较特殊的类型,介于值类型与引用类型之间。
如:
string a = "hello";
string b=a;
这时候,他们两个的引用地址是相同的,这样就与引用类型一样。
但是,区别就在下面了,在你去赋值的时候,就是在赋值的这一个过程中。如:
string b="world";
就是在这个赋值的过程中,就会被自动复制出一个相同的的值到另一块内存空间,然后在执行赋值操作,申请的内存长度要看你付新值的长度,如你新赋值的长度大于原字符长度,则申请与新字符长度相同长度的内存空间,如果新字符长度小于老字符长度,则申请老字符长度的空间。
而且要注意的是,每次增加他的长度,他都会从新申请内存来保存他,这也就是为什么在经常用到字符串叠加操作的时候建议使用 StringBuilder 的原因。
string是只读的引用类型。String类是不可变(final)的,对String类的任何改变,都是返回一个新的String类对象.这样的话把String类的引用传递给一个方法,该方法对String的任何改变,对原引用指向的对象没有任何影响,这一点和基本数据类型相似.
如果你这样调用是可以改变str的值的
string str = "abc";
Test(ref str);
MessageBox.Show(str);private void Test(ref string str)
{
str = str + "de";
}
string 是 String的别名,引用类型,没错。
但是,引用的指向可以改变吧。
string s = “Hello World”; // s指向“hello Wold"分配的内存空间
string s2 = s; //s2指向s,即“hello Wold"分配的内存空间
s2 = “GoodBye”; //s2又指向了“GoodBye”所分配的内存空间,(s指向不变,还是"hello world”)
1. string 是引用类型
引用类型操作
当使用重载操作符”=”给string对象赋值时,string的对象是引用类型,它保留在堆上,而不是堆栈上.因此,当把一个字符串赋给另一个字符串时,会得到对内存中同一个字符串的两个引用.例如,修改其中一个字符串,就会创建一个全新的string对象(注意,这个过程发生在”=”中),而另一个字符串没有改变.考虑下面的代码:
public class MyClass
{
public static void Main()
{
string str1 = "I am a number";
string str2 = str1;
Console.WriteLine("str1 = "+str1);
Console.WriteLine("str2 = "+str2);
str1 = "I am another number";
Console.WriteLine("after str1 changed... str1 = "+str1);
Console.WriteLine("after str1 changed... str2 = "+str2);
Console.ReadLine();
}
}
Output :
str1 = I am a number
str2 = I am a number
after str1 changed...str1 = I am another number
after str1 changed...str2 = I am a number
具有值类型特征的操作
string有两种情况下的操作是具有值类型特征的:
1) 在函数中传递string(比如函数参数是string型)时,传递的是地址,但却不能修改成员变量,原因是它重新又创建了一个全新的对象,和它想修改的那个成员变量非同一地址,所以看上去像是值类型;
2) str1 == str2 ,仅仅是比较了值,而非地址(是MS重写了==运算符所致).
总结:
string 到底是引用类型还是值类型 答:引用类型 . 只不过它在某此操作上会表现出值类型的特征.
string类型的另外一个特殊性在于它是“不会变”的,每次操作string,都相当于新建了一个string对象.
string s 创建一个对象
“Hello World”; 将信息赋值给s对象
string s2 又创建一个对象
将S对象的内容赋值给S2
后又将GoodBye赋值给S2 顶替原来的信息。
可以这么理解,S2对象,只能有一个指针,而GoodBye是最后所指的地址。