將內存中的字符串對象與引用這些對象的變量分開。如果你有一個變量命名爲value1
,你可以絕對告訴變量指向一個不同或新 string對象存儲:
string value1 = "foo";
value1 = "bar"; //this is fine
什麼你不能要做的就是改變記憶中的對象。字符串"foo"
使用的內存對象被認爲是不可變的。
以上面的代碼爲例,程序的第一行首先創建一個引用變量value1
。然後它創建一個值爲"foo"
的字符串對象,並最終分配value1
變量來引用內存中的"foo"
對象。第二行代碼不會更改內存中的"foo"
對象。相反,它會在內存中的新位置創建一個全新的字符串對象,其值爲"bar"
,並更新爲value1
變量以引用該新對象。內存中的原始"foo"
對象仍然存在,並且完全是未更改,但現在沒有任何引用它,並且可以在下次運行垃圾收集器時收集它。
讓我們看看一些代碼:
string value2 = "foo";
value2 = value2.Replace("foo", "bar");
value2.ToUpper();
//final result of value2 is "bar", not "BAR"
的第一行代碼這裏是有效的和以前一樣:新的變量,新的內存對象,並使前者指的是後者。第二行更有趣。在這裏,程序在value2
變量中查找參考,以查找內存中的"foo"
字符串對象,並調用該對象的Replace()
方法。此方法在內存中的全新位置返回新字符串對象,其值爲"bar"
。它確實不是修改內存中的現有"foo"
對象。新對象然後被分配到value2
變量。但還有一行代碼需要檢查。該程序再次查找value2
參考,在內存中找到"bar"
對象,並調用該對象的ToUpper()
方法。此方法還會返回一個全新的字符串對象,這次的值爲「BAR
」。但是,這次我們不會將該新對象分配給該變量。 value2
保持不變;它仍然指的是"bar"
字符串對象,它也沒有改變。因此,value2
的最終結果仍然是"bar"
。
請注意,並非所有類型都以此方式工作。大多數原語都可以,但更復雜的類型可以讓您更改基礎對象。
當他們告訴你字符串不可變時,這並不是他們的意思 – Jonesopolis
你誤解了字符串不能改變的含義。它們是不可改變的,但是沒有任何東西阻止你爲一個變量分配一個新的字符串。 – DavidG
這是我得到的,當我嘗試「名爲'value1'的本地或參數不能在此範圍內聲明,因爲該名稱用於封閉的本地範圍內以定義本地或參數」 – user3299251