为什么字符串对象引用不像其他对象引用?

时间:2010-05-10 16:52:17

标签: c#

string a = "a";

string b = a;

string a = "c";

为什么字符串b仍然具有值"a"而不是"c"

由于字符串是一个对象而不是堆栈值类型,这种行为是什么?

由于

6 个答案:

答案 0 :(得分:27)

你把变量指向一个新的东西,它与你说的

没什么不同
Foo a = new Foo();
Foo b = a;
a = new Foo();
// a no longer equal to b

在此示例中,b指向a最初引用的内容。通过更改a的值,ab不再引用内存中的同一对象。这与使用a和b的属性不同。

Foo a = new Foo();
Foo b = a;
a.Name = "Bar";
Console.WriteLine(b.Name);

在这种情况下,“Bar”会写入屏幕,因为ab仍然引用同一个对象。

答案 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

参见例如: http://codebetter.com/blogs/patricksmacchia/archive/2008/01/13/immutable-types-understand-them-and-use-them.aspx

答案 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所持有的引用仍指向旧字符串。