在 .NET 中,字符串是不可變的,這意味著一旦創(chuàng)建,字符串的內(nèi)容就不能被修改。字符串在內(nèi)存中以不同的方式存儲,具體取決于它是常量字符串還是動態(tài)創(chuàng)建的字符串。
常量字符串
常量字符串在編譯時就被解析,并在程序的元數(shù)據(jù)(Metadata)中存儲。多個相同的字符串常量可能會共享同一塊內(nèi)存。
string str1 = "Hello, ";
string str2 = "World!";
// 編譯時已知的字符串常量在元數(shù)據(jù)中被共享
string concatenated = str1 + str2;
Console.WriteLine(concatenated); // 輸出:Hello, World!
動態(tài)創(chuàng)建的字符串
動態(tài)創(chuàng)建的字符串通過堆內(nèi)存進(jìn)行存儲。每當(dāng)我們對字符串進(jìn)行修改時,實際上是創(chuàng)建了一個新的字符串對象,而原始的字符串對象保持不變。
string str = "Hello";
str += ", World!";
Console.WriteLine(str); // 輸出:Hello, World!
在上述例子中,str
的值在拼接后發(fā)生了變化,但實際上是創(chuàng)建了一個新的字符串對象,而原始的 "Hello" 字符串對象保持不變。
字符串池
.NET 框架使用了一個稱為字符串池(String Pool)的機制,它是一個位于堆中的數(shù)據(jù)結(jié)構(gòu),用于存儲字符串常量以及通過 string.Intern()
方法放入池中的字符串。字符串池的目的是為了重用字符串常量,減少內(nèi)存的使用。
string str1 = "Hello";
string str2 = "Hello";
bool areEqual = (str1 == str2); // true,因為它們指向字符串池中的同一對象
在這個例子中,str1
和 str2
實際上指向了字符串池中的同一對象,因此它們的內(nèi)容相等。
string str1 = new string("Hello".ToCharArray());
string str2 = new string("Hello".ToCharArray());
bool areEqual = (str1 == str2); // true,因為它們的內(nèi)容相等
bool referenceEqual = object.ReferenceEquals(str1, str2); // false,它們不指向同一對象
在這個例子中,str1
和 str2
的內(nèi)容相等,但它們不是同一對象,因為每次使用 new string(...)
都會創(chuàng)建一個新的字符串對象。
總的來說,字符串在內(nèi)存中的存儲方式主要有兩種:字符串常量和動態(tài)創(chuàng)建的字符串。字符串常量可以共享內(nèi)存,而動態(tài)創(chuàng)建的字符串存儲在堆上。字符串池用于存儲字符串常量,以便在需要時重用相同的字符串對象,減少內(nèi)存開銷。