2011-07-02 43 views
2

快速問題。有關在C中引用字符串的問題#

採取以下代碼示例:

ArrayList arrayList = new ArrayList(); 
string testString = ""; 
testString = "test"; 
arrayList.Add(testString); 

在此代碼示例,如果我要做到以下幾點:

arrayList[0] = "anotherTest"; 

會的TestString改爲anotherText或將保持不變?這是放入的對象還是其中一個副本,另一個字符串?

感謝, 基督教

+0

當你需要他時,Jon Skeet在哪裏? – Steve

+0

我仍然認爲不變性是這裏的核心概念。如果字符串WERE是可變的,那麼這個問題的答案會是相反的(假設'Add'複製參考而不是參考值)。我們可以在任何地方都有相同的參考,但該參考中的值將隨着'='運算符的變化而變化。每個人都假設OP知道每個字符串都等於'new String(「...」)'。但如果他這樣做了,他首先不會問這個問題。 – Steve

+0

這很棒。非常感謝你的答案,他們都很好。實際上,我將不得不再次提出這個問題,以獲得不同的代碼示例,一個實例化的類。再次感謝。 –

回答

4

前:

                  Before

後:

                  After

  • 只有ArrayList中的值[0]被改變爲參考 「anotherTest」。 testString變量的值保持不變。

  • 字符串是引用類型。這意味着testString變量和arrayList [0]每個(獨立地)都持有對對象「test」和「anotherTest」的引用,而不是值本身。

  • 將testString或arrayList [0]從一個字符串更改爲另一個字符串不會修改原始字符串。字符串是不可變的。只有對字符串對象的引用纔會更改。

+0

+1!感謝您根據其他不準確的答案爲此主題帶來一些理智。 – Domenic

+0

@Domenic,請參閱我對您評論的回覆。 – Steve

+0

這不是因爲字符串是引用類型,即使對於int也是一樣的 –

1

在您的例子要更新的列表它的自我,而不是被添加到列表中的原始字符串的第一個索引。

即使你不使用的字符串,例如一個Bitmap類,甚至是int結構:

int i = 14; 

List<int> myList = new List<int>(); 
myList.Add(i); 

myList[0] = 3; 

這會不會影響原來的我,它會保持14

另一件事你應該知道,String類-unlike其他類中普通的不變這樣:

string s1 = "some text"; 
string s2 = s1; 
s2 += " another text"; 

s1將保持不變。

普通類的不會是一成不變的,如:

class MyClass 
{ 
    public string MyString; 
} 

MyClass class1 = new MyClass(); 
class1.MyString = "Some String"; 
MyClas class2 = class1; 
class2.MyString = "Other String"; 

這將影響Class1的字符串作爲將因此現在是「其他字符串」,那是因爲類是全球化志願服務青年的類型。

+0

字符串不變性與此無關;即使字符串不可變也很容易重新分配'testString'的值,並且如果OP的問題是關於一種可變對象(即不是字符串),答案仍然是「否」。 – Domenic

+0

@Domenic:我還沒有完成我的答案。 –

+0

好了,現在你已經改變了你的答案,給出一個誤導性的例子,用'int'(代碼路徑完全不同,正如我自己的答案中所解釋的),以及一個完全不相關的字符串不變性旁註。 – Domenic

-2

您的問題的簡短答案是「否」。

爲什麼? 因爲字符串是不可變的。

這裏的原因:

維基百科:

如果一個對象被稱爲是不可變的, 它可以簡單地通過使基準的 拷貝到它,而不是 拷貝複製整個對象。 - 通過一個例子Wikipedia.org

讓我們一步:

var a = "Testing"; 
var b = a; 

在這裏,你已經有了一個字符串(「測試」)在內存坐在某個位置(假設位置0×001所以。實際值「a」的第一行變成0×001。

而且我們設置b = A,第二行...所以b也被設置爲0×001(因爲我們複製引用)。

現在,假設我們這樣做:

a = "Again"; 

在這裏,我們有另一個字符串(「再」)坐在記憶一些不同的位置(假設位置0x022)。

我們知道字符串是不可變的......所以這裏會發生什麼?那麼......這意味着我們通過引用來分配。所以,「a」的值變爲0x022。

這對「b」意味着什麼?這意味着,任何指向0x001(「測試」)的變量將仍然指向0x001 ...因此,在這種情況下,「b」仍保持不變。

而只有「a」,我們通過更改它的參考進行更新將指向0x022。

+0

字符串不可變性與此無關,字符串不會被傳遞。 – Domenic

+0

@Domenic,它有一些與它有關的事情,因爲真正的問題是關於幕後的參考。將問題改爲:「如果我有一個表示對字符串的引用的變量,並且爲該變量分配了一個新的字符串值,引用是否改變,或者引用位置的值是否發生了變化?事實上,這個問題是關於可變性的,如果該位置的值可能會被突變,那麼對該位置的其他引用將會被更新。 – Steve

+0

只有在每個引用都是「可變的」的意義上,「可變性」纔是問題,因爲您可以使用equals運算符來「引用」它所引用的內容。它與string(im)可變性無關。 – Domenic

-1

那麼,你總是可以運行代碼來找出;)。

答案是testString不會改變。 @ dtb的答案解釋了原因。我會解決問題的另一個方面,關於你的「這是放入的對象還是其副本,另一個字符串?」題。

讓我們打破了什麼事情在你的代碼:

  • testString包含"test"參考。
  • 調用arrayList.add(testString)設置arrayList[0]是對"test"的參考。
  • arrayList[0] = "anotherTest"arrayList[0]是對"anotherTest"的參考。

所以,正如你所看到的,沒有複製正在進行。字符串不會被複制,或者(像其他答案所說的那樣)「按值傳遞」。


如果你的問題是關於一個值類型,就像一個struct甚至只是int,那麼答案將仍然testInt沒有改變,但在情況的原因是發生了複製:值類型「按值傳遞」,並且在使用=運算符時會創建它們的副本。

+0

如果downvoters可以解釋我的帖子的哪一部分在技術上不準確,但是我敢肯定在這個帖子上的投票只是人們捍衛傷害感情,現在給所有的-1s漂浮在附近:) – Domenic

+0

Right ,在我說的引用類型(包括'string')的水平線之前,在那之後,我正在談論一個涉及價值類型的假設情況,以澄清在這種假設情況下會發生「複製」,即使它不在OP的情況下。那不清楚嗎? – Domenic

+0

好的,對不起。那麼,要說清楚,你說的是不變性與它無關?因爲我認爲你所說的與你的定義很相似......並且我同意這一點。 – Steve

0

事實上,到目前爲止,三個答案都不是很準確。

testString變量在示例中始終保存對「test」的引用。 它永遠不會改變。

更重要的是,ArrayList也是一個包含對象引用的容器。所以當你給第0個元素賦「anotherTest」時,你實際上會讓第0個元素引用一個不同的字符串對象。這不會改變testString的值。

2

這裏有2個對象:「test」和「anotherTest」。

階段1:

arrayList.Add(testString) //Adds the reference stored in testString 
          //to the end of arrayList. 

這條線的執行後,ArrayList的[0]還包含一個參考到「測試」(因爲在這個階段,的TestString包含到對象「測試」的引用) 。

您可以檢查此:

Console.WriteLine(object.ReferenceEquals(testString, arrayList[0])); //outputs true 

第2階段:

arrayList[0] = "anotherTest"; //stores a reference to the object "anotherTest" in 
           //arrayList[0] 

我們沒有改變的TestString的。它仍然引用「測試」。可以再檢查一下,存儲在數組列表[0]和的TestString的參考文獻是不同的:

Console.WriteLine(object.ReferenceEquals(testString, arrayList[0])); //outputs false 

的TestString - >存儲參照 「測試」
ArrayList的[0] - >存儲提及 「anotherTest」

2

當你已經完成了第一個代碼塊

ArrayList arrayList = new ArrayList(); 
string testString = ""; 
testString = "test"; 
arrayList.Add(testString); 

你有兩個引用一到arrayList和一到testString

arrayList中的第一個元素引用與testString相同的對象,即值爲"test"的字符串。

數組列表確實包含對testString對象的引用,但數組列表項0和testString變量都引用相同的對象。

當你做作業

`arrayList[0] = "anotherTest";` 

你隱式實例包含"anotherTest"string對象。該對象存儲在索引爲null的數組項中。

因此,在第二塊數組列表項0引用新的字符串對象並且testString繼續引用原始字符串。