简体   繁体   English

如果不能更改不可变的字符串变量,为什么要更改它呢?

[英]Why can you change an immutable string variable if it cannot be changed?

This might have been asked somewhere else but I just did not see it when I did a simple search. 这可能是在其他地方询问的,但是当我进行简单搜索时,我只是没有看到它。 I am taking a C# class for work and I do know that string is immutable and stringBuilder can be changed through out the code. 我正在使用C#类进行工作,我确实知道字符串是不可变的,并且可以通过代码更改stringBuilder。

But why does C# let you change the string if it is immutable? 但是,如果C#不可变,为什么C#允许您更改它呢?

Or does it let you change the string because it take a new memory spot and creates another hole string variable and abandons the other variable address location. 还是让您更改字符串,因为它占用了一个新的内存点并创建了另一个孔字符串变量,并放弃了另一个变量地址位置。 If this is the case and the automatic garbage collection comes through and tidies up the C# memory locations does it really matter if a person uses string or stringBuilder? 如果是这种情况,并且自动进行垃圾收集并整理C#内存位置,那么一个人使用string或stringBuilder真的重要吗?

Code: 码:

        string sss = 'abcd';
        sss = 'ghy';
        sss = 'nnnnnn';

That's changing the value of a variable by assigning the variable to a different value. 通过将变量分配给其他值来更改变量的值。

That is not mutating the value to which the variable refers. 但这并不会使变量引用的值发生变化。

You've basically answered the question yourself. 您基本上已经自己回答了这个问题。 The short answer is " C# does not let you change the string" 简短的回答是“C# 不会让你改变字符串”

For various design reasons, "String" in c# is implemented as a reference-type . 由于各种设计原因,c#中的“字符串”被实现为引用类型 What you're doing is changing the what sss references - you're not changing the thing that's being referenced. 您正在做的是更改sss引用的内容-您并没有更改被引用的内容。 'abcd' exists separately from 'ghy' exists separately from 'nnnnnn' You're not changing one thing into another thing. “ abcd”与“ ghy”独立存在,与“ nnnnnn”独立存在您不会将一件事变成另一件事。 You're creating a whole new thing, and then changing which one sss references. 您正在创建一种全新的事物,然后更改一个sss引用。

Strings are immutable in C# to make them behave like value-types even though they're implemented as reference types . 字符串在C#中是不可变的,即使它们被实现引用类型 ,也使它们的行为类似于 类型 Why? 为什么? Because the alternative is worse: 因为替代方案更糟:

Consider an example where strings are reference types, but aren't immutable - and you can change 'abcd' into 'ab12'. 考虑一个示例,其中字符串是引用类型,但不是不变的-您可以将'abcd'更改为'ab12'。 How would that look? 看起来如何?

string mutableString = "abcd";
string anotherRef = mutableString;

mutableString.mutateTo("ab12"); //A method that doesn't exist - for exposition only

at this point anotherRef would also be "ab12" - which seems very unintuitive. 在这一点上,anotherRef也将是“ ab12”-似乎非常不直观。

Regarding String Builder: 关于字符串生成器:

StringBuilder is more of a performance thing that's used in special cases. StringBuilder更像是在特殊情况下使用的性能产品。 For most string concatenation, it doesn't matter. 对于大多数字符串连接而言,都没有关系。 If you have two strings like "My name is" and "Pete" and you concatenate them - then you'll end up with a new string "My name is Pete" and the old strings will probably be stuck around in memory somewhere. 如果您有两个字符串,例如“我的名字是”和“ Pete”,并且将它们串联起来,那么您将得到一个新的字符串“我的名字是Pete”,而旧的字符串可能会卡在内存中的某个地方。 Not a big deal. 没有大碍。 You have the full string that you want - not a lot of time or memory wasted. 您拥有了所需的完整字符串-不会浪费很多时间或内存。 Consider a more extreme case though: What if you have more words: "The" "quick" "brown" "fox" "jumps" "over" "the" "lazy" "dog" and you want to concatenate them all together: 但是,请考虑一个更极端的情况:如果您有更多的单词,该怎么办:“ The”,“ quick”,“ brown”,“ fox”,“ jumps”,“ over”,“ the”,“ lazy”,“ dog”,并且您想将它们全部串联在一起:

  1. "The" + "quick" yields "The quick" (a new string) “ The” +“ quick”产生“ The quick”(新字符串)
  2. "The quick" + "brown" yields "The quick brown" (another new string) “快速” +“棕色”产生“快速棕色”(另一个新字符串)
  3. "The quick brown" + "fox" yields "The quick brown fox" (another new string - getting longer) “快速棕色” +“狐狸”产生“快速棕色狐狸”(另一个新琴弦-更长)
  4. "The quick brown fox" + "jumps" yields "The quick brown fox jumps" (another new string - each more expensive than the last!) “快速的棕色狐狸” +“跳跃”产生“快速的棕色狐狸跳跃”(另一条新的弦-每根都比上一根贵!)
  5. etc. . 等。 .

You can see that this method results in a lot of extra intermediate strings that you don't really care about, but they'll all be allocated - which takes time - and they'll all hang around in memory until the GC gets rid of them. 您会看到此方法会导致很多您真正不在乎的中间字符串,但是它们将全部分配(这需要时间),并且它们将一直在内存中徘徊,直到GC被清除为止他们。 StringBuilder gives you a method to do the concatenation without having to allocate every one of the intermediate results. StringBuilder为您提供了一种进行连接的方法,而不必分配每个中间结果。

Note - this next part isn't strictly true, but it's close enough for this example. 注意-下一部分并不是严格意义上的,但是对于本示例来说已经足够接近了。 There is no contractual behavior for the internal implementation of StringBuilder: You can think of it as "Lazy concatenation." StringBuilder的内部实现没有契约行为:您可以将其视为“惰性串联”。 It can hold references to all of the component strings internally, but won't reallocate space for the final result until you call the ToString method when you're done appending strings. 它可以在内部保存对所有组件字符串的引用,但是在添加完字符串之后调用ToString方法之前,不会为最终结果重新分配空间。 This lets it compute the final size that it needs to be, and reallocate enough space for the whole combined string - once instead of n times. 这样就可以计算最终所需的大小,并为整个组合字符串重新分配足够的空间- 一次而不是n次。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM