字符串不变性在向开发人员解释字符串引用时扮演什么角色?

发布于 11-18 03:19 字数 874 浏览 1 评论 0原文

我经常以某种形式遇到以下问题(此处以伪代码提出):

String myString = "Hello"
someObject.stringProperty = myString
myString = "World"

为什么 someObject.stringProperty 现在不等于“World”?

以下陈述在解释为什么会出现这种情况时所扮演的角色似乎令人困惑:

字符串是不可变的

你觉得怎么样?

如果您认为该声明不适用,我会问您:在字符串可变的语言中,并且赋值运算符改变了它们的实际值(而不是简单地更改引用),会你的回答还有道理吗?

编辑:

好的,我觉得有必要澄清一些事情:

  1. 我对字符串、引用或赋值的工作原理并不感到困惑。我对这个话题非常清楚。我不是在问字符串是如何工作的。我问“字符串不变性在向开发人员解释字符串引用方面发挥什么作用”。我们可以跳过我一定感到困惑的人身攻击。

  2. 我正在为提出所引用问题的开发人员寻找逻辑上严格的答案,该答案不包含或预先假设字符串的不变性。

现有参数的分类:

  1. 字符串不变性与之无关,因为引用正在改变,而不是字符串的值这个答案预先假设了我所询问的确切事实。

  2. 赋值意味着引用的赋值而不是值的赋值同样,这预先假设了我所询问的确切事实。对于字符串来说,没有理由一定是这种情况。出于性能和其他原因,字符串就是如此。

In one form or another I encounter the following question often (posed, here, in pseudo-code):

String myString = "Hello"
someObject.stringProperty = myString
myString = "World"

Why doesn't someObject.stringProperty now equal "World"?

There seems to be confusion about the role the following statement plays in the explanation of why this is the case:

Strings are Immutable

What do you think?

If you think the statement doesn't apply, I'd ask you this: In a language where strings were mutable, and the assignment operator mutated their actual value (instead of simply changing the reference), would your answer still make sense?

EDIT:

OK, I feel the need to clarify some things:

  1. I'm not confused about how strings, references, or assignments work. I'm perfectly clear on this topic. I'm not asking how strings work. I'm asking "What role does string immutability play in the explaination of string references to developers". We can skip the Ad-Hominem attacks that I must be confused.

  2. I'm looking for a logically rigorous answer for the developer asking the cited question which doesn't contain, or pre-suppose, the immutability of strings.

A categorization of the existing arguments:

  1. String Immutability has nothing to do with it because the references are changing, not the values of the strings This answer pre-supposes the exact fact I'm asking about.

  2. Assignment means assignment of references not assignment of values Again, this pre-supposes the exact fact I'm asking about. There is no reason this must be the case for strings. It simply is the case for strings for performance and other reasons.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

清晨说晚安2024-11-25 03:19:57

陈述在解释中所起的作用取决于解释本身。它可能是有害的,也可能是有用的,这取决于其余的解释。

就我个人而言,直到解释的相当晚的时候我才会使用该声明(至少现在是这样)。字符串的不变性只是在某种程度上造成了阻碍——就像参数传递解释一样。我将首先使用可变类进行解释,如下所示:

House x = new House(Color.Green); // The has a green front door
House y = x;
x = new House(Color.Red);
Console.WriteLine(y.FrontDoorColor); // Still green!

在这里,我将解释 xy 就像一张写有房屋地址的纸。第二行中的赋值并不复制房屋 - 它复制房屋的地址。第三行的分配不会改变第一栋房子前门的颜色 - 它创建一个新房子,然后擦掉第一栋房子的地址纸 (x),并写下新地址。这不会改变第一栋房子或第二张纸 (y) 的任何内容。

然后我会给出第二个例子:

House x = new House(Color.Green); // The has a green front door
House y = x;
x.FrontDoorColor = Color.Red; // Repainting a front door
Console.WriteLine(y.FrontDoorColor); // Red!

这次只有一栋房子 - 如果我粉刷一栋房子的门,你用我之前给你的地址来看它,你会看到前门现在是红色的。

到目前为止,一切都很好。 现在我可以回到原来的例子并说它已经看起来像第一个房子片段而不是第二个,所以它的行为是相同的。然后我可以说,字符串不变性意味着您甚至无法编写看起来像第二个房子示例但使用字符串的代码。因此,字符串不变性不会立即与现有代码的解释相关,但它仍然会出现在同一个答案中。

(我还必须指出,虽然引用的行为类似于真实世界的地址,但我并不声称它们与“内存地址”或指针相同。它们不必是。我在使用该术语严格的与现实世界的类比,仅此而已。这是该示例的缺点,但我认为它不会造成太大伤害。)

然后我可能还会讨论值类型,并考虑会发生什么 。如果 House 是值类型,就会发生这种情况 - 并且不鼓励可变值类型。

要知道我的答案是否仍然与具有可变字符串的语言相关,我们需要更多地了解字符串文字的行为方式。除了字符串的可变性之外,在所有方面都与 C# 相同的语言将是一种糟糕的语言,正如您可以写的那样:

// Hypothetical bad language
string x = "dog";
x.MutateTo("cat");
Console.WriteLine("dog"); // Prints cat!

这显然是不可取的,因此可能是字符串文字的行为就必须改变。您还讨论了赋值运算符的含义可能发生的变化,等等……如果不确切了解假设的语言的行为方式,就很难对它做出具体的陈述。

The role played by the statement in the explanation depends on the explanation itself. It could be harmful or useful, depending on the rest of the explanation.

Personally I wouldn't use that statement until fairly late in the explanation (at least these days). The immutability of strings just gets in the way somewhat - as it does with parameter passing explanations. I'd start with an explanation using a mutable class, like this:

House x = new House(Color.Green); // The has a green front door
House y = x;
x = new House(Color.Red);
Console.WriteLine(y.FrontDoorColor); // Still green!

Here I would explain that x and y are like pieces of paper with the addresses of houses on. The assignment in the second line doesn't copy a house - it copies the address of a house. The assignment on the third line doesn't change the color of the front door on the first house - it creates a new house, then rubs out the address on the first piece of paper (x), and writes the new address on. This doesn't change anything about the first house, or the second piece of paper (y).

I'd then produce a second example:

House x = new House(Color.Green); // The has a green front door
House y = x;
x.FrontDoorColor = Color.Red; // Repainting a front door
Console.WriteLine(y.FrontDoorColor); // Red!

This time there's only one house - if I paint the door of a house and you come to see it with the address I'd given you earlier, you'll see the front door is now red.

So far, so good. Now I could go back to the original example and say that it already looks like the first house snippet rather than the second one, so it behaves the same way. I can then say that string immutability means you can't even write code that looks like the second house example but using strings. So string immutability wouldn't have been immediately relevant to the explanation of the existing code, but it would still have appeared in the same answer.

(I'd also have to point out that although references behave like real-world addresses, I'm not claiming that they're the same as "memory addresses" or pointers. They don't have to be. I'm using the term in a strict analogy to the real world, and that's all. It's a downside of the example, but I don't think it does too much harm.)

I might then also talk about value types, and consider what would have happened if House had been a value type - as well as discouraging mutable value types.

To know whether or not my answer would still be relevant in a language with mutable strings, we'd need to know more about how string literals behaved. A language which was the same as C# in every way other than the mutability of strings would be an awful language, as you could write:

// Hypothetical bad language
string x = "dog";
x.MutateTo("cat");
Console.WriteLine("dog"); // Prints cat!

That clearly wouldn't be desirable, so presumably the behaviour of string literals would have to change. You also talk about possible changes to the meaning of the assignment operator, etc... it's hard to make concrete statements about a hypothetical language without knowing exactly how it behaves.

玩套路吗2024-11-25 03:19:57

这是因为计算机编程中的等号更多的是赋值运算符,而不是“数学相等”条件。字符串不可变与它无关。这都是关于等号是“赋值”运算符而不是数学等价约束。

这意味着 A = B;且 B = C;并不意味着 A = C;

相反,这意味着

A 已被设置为引用 B 的值,因此 B 的值现在是 A 的值。
B 已被设置为引用 C 的值,因此 C 的值现在是 B 的值,但 A 的值保持不变

如果字符串不是不可变的

String myString = "Hello";
myString.replace(3, "p"); // replace starting at char #3 (the second 'l')
System.out.println(myString); // would print "Help"

但由于字符串是不可变的;

String myString = "Hello";
myString.replace(3, "p"); // returns a new string "help" which is not assigned to anything
// since the newly returned string was not assigned to anything, it was garbage collected
System.out.println(myString); // would print "Hello"

It is because the equals sign in computer programming is more of an assignment operator than an "mathematical equality" condition. That the string is immutable has nothing to do with it. This is all about the equals sign being a "assignment" operator rather than a mathematical equivalence constraint.

This means that A = B; and B = C; does not imply that A = C;

instead it means

A has been set to reference the value of B, so B's value is now A's value.
B has been set to reference the value of C, so C's value is now B's value, but A's value remains unchanged

If strings were not immutable

String myString = "Hello";
myString.replace(3, "p"); // replace starting at char #3 (the second 'l')
System.out.println(myString); // would print "Help"

But since Strings are immutable;

String myString = "Hello";
myString.replace(3, "p"); // returns a new string "help" which is not assigned to anything
// since the newly returned string was not assigned to anything, it was garbage collected
System.out.println(myString); // would print "Hello"
怎樣才叫好2024-11-25 03:19:57

解释是这个例子与不变性无关。

您有两个变量最初包含相同的值,这对于字符串来说意味着它们指向内存中的同一个对象。然后更改其中一个变量的值并将其指向内存中的另一个对象。

这与说

int a = 4;
int b = a;
a = 5; 

Or

string x = "Foo";
string y = x;
x = "Bar";

Or

Foo foo = new Foo() { Bar = 42 };
Foo otherFoo = foo;
foo = new Foo() { Bar = 17; }

没有什么不同。变量暂时引用相同的事物。它们并不是一直密不可分的。一旦你把一个人指向别的东西,他们的共性就结束了。

The explanation is that this example has nothing to do with immutability.

You have two variables originally containing the same value, which for a string means they are pointing to the same object in memory. You then change the value of one of the variables and point it to another object in memory.

It is no different than saying

int a = 4;
int b = a;
a = 5; 

Or

string x = "Foo";
string y = x;
x = "Bar";

Or

Foo foo = new Foo() { Bar = 42 };
Foo otherFoo = foo;
foo = new Foo() { Bar = 17; }

The variables momentarily reference the same thing. They are not otherwise inextricably linked for all time. As soon as you point one to something else, their commonality ends.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文