快速提问。
采用以下代码示例:
ArrayList arrayList = new ArrayList();
string testString = "";
testString = "test";
arrayList.Add(testString);
在该代码示例中,如果我要执行以下操作:
arrayList[0] = "anotherTest";
将testString更改为anotherText还是保持不变?它是放入的对象还是它的副本,另一个字符串?
谢谢, 基督教
答案 0 :(得分:4)
之前:
后:
只有arrayList [0]的值更改为对“anotherTest”的引用。 testString变量的值保持不变。
String是引用类型。这意味着testString变量和arrayList [0]每个(独立地)都拥有对象“test”和“anotherTest”的引用,而不是值本身。
将testString或arrayList [0]从一个字符串更改为另一个字符串不会修改原始字符串。字符串是不可变的。只更改了对字符串对象的引用。
答案 1 :(得分:2)
这里有2个对象:“test”和“anotherTest”。
第1阶段:
arrayList.Add(testString) //Adds the reference stored in testString
//to the end of arrayList.
执行此行后,arrayList [0]还包含对“test”的引用(因为在此阶段,testString包含对象“test”的引用)。
您可以查看:
Console.WriteLine(object.ReferenceEquals(testString, arrayList[0])); //outputs true
第二阶段:
arrayList[0] = "anotherTest"; //stores a reference to the object "anotherTest" in
//arrayList[0]
我们根本没有改变testString。它仍然引用“测试”。您可以知道存储在arrayList [0]和testString中的引用是不同的:
Console.WriteLine(object.ReferenceEquals(testString, arrayList[0])); //outputs false
testString - >商店参考“测试”
arrayList [0] - >存储引用“anotherTest”
答案 2 :(得分:2)
完成第一个代码块后
ArrayList arrayList = new ArrayList();
string testString = "";
testString = "test";
arrayList.Add(testString);
您有两个引用arrayList
,一个引用testString
。
arrayList
中的第一个元素引用与testString
相同的对象,即值为"test"
的字符串。
arraylist确实包含对testString
对象的引用,但是arraylist item 0和testString
变量都引用了同一个对象。
执行作业时
`arrayList[0] = "anotherTest";`
您隐式实例化包含string
的新"anotherTest"
对象。此对象存储在索引为null的数组项中。
所以在第二个块之后,arraylist第0项引用了新的字符串对象,testString
继续引用原始字符串。
答案 3 :(得分:1)
在您的示例中,您正在更新列表的第一个索引,而不是添加到列表中的原始字符串。
即使你没有使用字符串,例如Bitmap
类,甚至是int
结构:
int i = 14;
List<int> myList = new List<int>();
myList.Add(i);
myList[0] = 3;
这不会影响原始i,它将保持为14。
另一件事你应该知道字符串类 - 通常不像其他类 - 是不可变的所以:
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字符串,因此它现在是“Other String”,因为这些类是referance类型。
答案 4 :(得分:0)
事实上,到目前为止,三个答案中没有一个是非常准确的。
testString变量始终在示例中保存对“test”的引用。 它永远不会改变。
更重要的是ArrayList也是一个包含对象引用的容器。因此,当您将“anotherTest”分配给第0个元素时,实际上使第0个元素引用为不同的字符串对象。这不会改变testString的值。
答案 5 :(得分:-1)
好吧,你总是可以运行代码来查找;)。
答案是testString
不会改变。 @ dtb的答案解释了原因。我将解决问题的另一个方面,关于你的“是放入的对象还是它的副本,另一个字符串?”问题
让我们分解代码中的内容:
testString
包含对"test"
。arrayList.add(testString)
集arrayList[0]
作为对"test"
的引用。arrayList[0] = "anotherTest"
设置arrayList[0]
作为对"anotherTest"
的引用。所以,正如你所看到的,永远都没有复制。字符串不会被复制,或者(正如其他一些答案所说的那样)“按值传递”。
如果您的问题是关于值类型,例如struct
甚至只是int
,那么答案仍然那个{ {1}}未更改,但在 情况下,原因是复制已经发生:值类型 “按值传递”,并且它们的副本确实得到了使用testInt
运算符时创建。
答案 6 :(得分:-2)
对你的问题的简短回答是“不”。
为什么呢? 因为字符串是不可变的。
原因如下:
来自维基百科:
如果已知某个对象是不可变的, 它可以简单地通过制作来复制 引用它的副本而不是 复制整个对象。 - Wikipedia.org
我们来看一个例子:
var a = "Testing";
var b = a;
在这里,你已经有一个字符串(“Testing”)坐在内存中的某个位置(假设位置为0x001。所以,“a”的实际值在第一行变为0x001。
我们在第二行设置b = a ...所以b也设置为0x001(因为我们正在复制引用)。
现在,假设我们这样做:
a = "Again";
这里,我们有另一个字符串(“Again”)坐在内存中的某个不同位置(假设位置为0x022)。
我们知道字符串是不可变的...所以这里发生了什么?嗯......这意味着我们通过引用分配。因此,“a”的值变为0x022。
这对“b”意味着什么?
这意味着,任何指向0x001(“Testing”)的变量都将STILL指向0x001 ...因此,在这种情况下,“b”仍然是UNCHANGED。
只有通过更改引用更新的“a”才会指向0x022。