string a = "a";
string b = a;
string a = "c";
为什么字符串b
仍然具有值"a"
而不是"c"
?
由于字符串是一个对象而不是堆栈值类型,这种行为是什么?
由于
答案 0 :(得分:27)
你把变量指向一个新的东西,它与你说的
没什么不同Foo a = new Foo();
Foo b = a;
a = new Foo();
// a no longer equal to b
在此示例中,b
指向a
最初引用的内容。通过更改a
的值,a
和b
不再引用内存中的同一对象。这与使用a和b的属性不同。
Foo a = new Foo();
Foo b = a;
a.Name = "Bar";
Console.WriteLine(b.Name);
在这种情况下,“Bar”会写入屏幕,因为a
和b
仍然引用同一个对象。
答案 1 :(得分:21)
首先让我说你对变量和数据的选择很差。这使得某人很难说“你的例子中的字符串a ......”因为“a”可能是字符串的内容,或者包含变量参考资料。 (并且它很容易与不定冠词'a'混淆。)
此外,您的代码无法编译,因为它声明变量“a”两次。如果你以一种让他们能够明确回答问题的方式提出问题,你可能会得到更好的答案。
让我们重新开始吧。
我们有两个变量和两个字符串文字。
string x = "hello";
string y = x;
x = "goodbye";
现在的问题是“为什么y等于'你好'而不是'再见'”?
让我们回到基础。什么是变量? 变量是存储位置。
字符串类型的值是多少? 字符串类型的值是对字符串数据的引用。。
什么是字符串类型的变量?把它放在一起。 string类型的变量是一个存储位置,它保存对字符串数据的引用。
那么,什么是x?存储位置。它的第一个价值是什么?对字符串数据“hello”的引用。
你是什么?存储位置。它的第一个价值是什么?字符串数据“hello”的引用,与x相同。
现在我们更改存储位置x的内容以引用字符串数据“goodbye”。存储位置y的内容不变;我们没有设置y。
有意义吗?
为什么字符串对象引用不像其他对象引用?
我否认这个问题的前提。 String对象引用 do 的行为与其他对象引用类似。你能举例说明他们不在哪里吗?
答案 2 :(得分:3)
让人们如此困惑的部分原因是将以下内容视为追加操作:
str1 = str1 + str2;
如果string
是一个可变类型,上面的内容是这样的简写:
str1.Append(str2);
那么你所要求的是有意义的。
但是str1 = str1 + str2
不仅仅是对可变对象的一些方法调用;这是作业。实现这一点清楚地表明,在您的示例中设置a = "c"
与将任何变量(引用类型或非引用类型)分配给新的内容没有区别。
处理两个List<char>
对象的代码和处理两个string
对象的代码之间的下面比较应该会更清楚。
var a = new List<char>();
var b = a; // at this point, a and b refer to the same List<char>
b.Add('a'); // since a and b refer to the same List<char> ...
if (b.Contains('a')) { /* ...this is true... */ }
if (a.Contains('a')) { /* ...and so is this */ }
// HOWEVER...
a = new List<char>(); // now a and b do NOT refer to the same List<char>...
if (b.Contains('a')) { /* ...so this is still true... */ }
if (a.Contains('a')) { /* ...but this is not */ }
将此与您发布的代码的略微修改版本进行比较:
string a = "a";
string b = a; // at this point, a and b refer to the same string ("a")...
if (b == "a") { /* ...so this is true... */ }
if (a == "a") { /* ...and so is this */ }
// REMEMBER: the below is not simply an append operation like List<T>.Add --
// it is an ASSIGNMENT
a = a + "c"; // now they do not -- b is still "c", but a is "ac"
if (b == "a") { /* ...so this is still true... */ }
if (a == "a") { /* ...but this is not */ }
答案 3 :(得分:2)
在.Net中,a,b和c是对象的引用,而不是对象本身。重置a时,您将此引用指向新的内存位置。旧的内存位置及其任何引用都没有改变。
答案 4 :(得分:0)
我猜OP认为字符串对象是可变的,所以像var = "content";
这样的东西
实际上会将新的字符数组存储在已存在的对象中。
但是,String是一个不可变类型,这意味着在这种情况下会创建一个新的字符串对象并将其分配给var
。
答案 5 :(得分:0)
由于c#的内置字符串支持,这是一种误解。
string a = "123"; //The way to write it in C#
string a = new string("123"); //Would be more obvious
定义a的第二种方式更明显发生了什么,但它是详细的。因为字符串直接支持编译器调用字符串构造函数是不必要的。
编写你的例子详细:
string a = new string("a");
string b = a;
string a = new string("c");
此处行为与预期一致,获取对指定的新字符串对象的引用。而b所持有的引用仍指向旧字符串。