在c#里面,string类型被划分为引用类型。但是从严格意义上来说,它即不是引用类型也不是值类型,因为它即具备引用类型的特点,同时也具备值类型的特点。
我们来看一个例子:
static void Main(string[] args)
{
string a = "hello";
string b = "hello";
if (string.ReferenceEquals(a, b))
{
Console.WriteLine("a和b的引用地址一致!");
a = "nihao";
Console.WriteLine("a={0},b={1}", a, b);
if(string.ReferenceEquals(a, b))
{
Console.WriteLine("修改a的值后,a和b的引用地址一致!");
}
else
{
Console.WriteLine("修改a的值后,a和b的引用地址不一致!");
}
}
else
{
Console.WriteLine("a和b的引用地址不一致!");
}
Console.ReadKey();
}
ReferenceEquals这个函数的作用是判读两个对象的引用是否相同,从运行结果来看,a和b的引用地址是一样的。然后修改了a的值,a和b的引用地址就不一样了。
这种特性即不是值类型也不是引用类型所具备的,这说明字符串类型的存储原理和这两种类型的不一样。
字符串的存储原理:当创建一个字符串对象时,会在内存创建一个字符串常量。每次创建一个字符串时都会去字符串常量区中查询这个字符串是否已经创建了,如果已经创建了,就把已经创建的字符串的引用赋值给新创建的字符串,这两个字符串就引用了同一个引用地址,这就解释了上面的a和b在修改之前的引用为什么是相同的;如果没有查询到字符串的值,则创建一个新的字符串常量。
当修改字符串的值时会创建一个新的字符串对象,并会分配一个新的引用,所以修改a的值后,a和b的引用就不一致了。