可能是因为它是不可变的。
class A
{
public string a;
}
static void Main(string[] args)
{
A a1 = new A();
A b1 = new A();
string a = "abc";
a1.a = "abc";
string b = "ca";
b1.a = "ca";
a = b;
a1 = b1;
b = "cab";
b1.a = "cab";
Console.WriteLine(a);
Console.WriteLine(a1.a);
Console.ReadLine();
}
a1.a的答案是“ca”和a“a”的“cab”,这就是我在面试问题中回答的问题,我将原因解释为字符串的“不变性”。
但面试官并不相信。有人可以提供上述代码的令人信服的解释吗?
答案 0 :(得分:8)
这种情况对于不变性有 。这完全取决于引用类型的工作原理。
在你的;
a = b;
行,您的b
和a
引用指向同一个对象"ca"
并且更改b
对另一个对象的引用不会影响{{1分数。
让我试着逐行解释这里发生的事情;
首先,string
是引用类型,引用类型有2个部分。该对象的对象和引用。
在你的
中a
行,你有一个string a = "abc";
对象和一个名为"abc"
的对象的引用。
a
在这一行中,您有一个string b = "ca";
对象和一个名为"ca"
的对象的引用。
b
在此行中,现在a = b;
引用指向a
引用点为b
的同一对象。
"ca"
在此行中,您创建了一个名为b = "cab";
的新对象,而您的"cab"
引用现在指向此对象。它不再指向b
个对象。
"ca"
在此行中,由于Console.WriteLine(a);
仍然引用a
对象,因此将打印此字符串。更改"ca"
引用的对象不会影响它。
答案 1 :(得分:1)
没有字符串不变的情况。该字符串是引用类型。最初,您将a
设置为指向值为“abc”的字符串。将b
设置为指向值为ca
的字符串时。之后,您将a
设为等于b
。由于它们都是引用类型,a
现在指向b
所指向的位置。换句话说,现在a
指向ca
。稍后您只需更改b
指向的位置。此更改不会影响a
指向的值。
答案 2 :(得分:1)
这更多地与C#中指针和引用之间的区别有关。
a = b,你不会指向现在和未来的任何b。您不能将指针变量a分配给指针变量b(C ++指针的行为方式)。
因为它们是引用,所以在当时保存的任何(字符串) 值 b初始化。就是这样,与b的任何其他联系都会丢失。
它就像一个复制构造函数,为a创建了一个新的字符串值。当b再次改变时,a不会受到影响。因为它们拥有不同的物体!
修改强>
复制过程的更正:实际上没有创建新对象。与指针不同的是在该时间点的对象的内存地址的一次性分配。 a将指向相同的字符串值,在内存中,由b 在该时间点保持并且它是,将来不再与b相关联。
答案 3 :(得分:1)
虽然Sonor的答案很精彩且正确,但却忽略了一个重要的观点。整点都与字符串无关。这个谜题与整数完全相同:
class A
{
public int a;
}
static void Main(string[] args)
{
A a1 = new A();
A b1 = new A();
int a = 123;
a1.a = 123;
int b = 31;
b1.a = 31;
a = b;
a1 = b1;
b = 312;
b1.a = 312;
Console.WriteLine(a);
Console.WriteLine(a1.a);
Console.ReadLine();
}
关键事实是a1和b1是参考。 (不是a和b)
答案 4 :(得分:0)
这个问题实际上解决了我对字符串文字的一些误解。
string a="abc";
的含义是什么?我实际上是将“abc”视为a
指向的值。
但这部分是正确的。
“abc”是字符串文字,它本身就是一个字符串对象(由ldstr IL指令创建),如下面的链接所示,该语句基本上使a
局部变量指向字符串文字
Why don't we use new operator while initializing a string?
以下代码对我意味着什么?
string b = "ca";
a = b;
b = "cab";
我认为"cab"
作为b
指向的值的更新,因此a
也将更新。
我认为由于字符串的不变性,价值不会得到更新。
但由于字符串文字不是一个值,而是一个等同于以下代码的对象:(因此给出了我的问题的答案)
string b = "ca";
a = b;
string c = "cab";
b = c;