为什么 .NET 字符串是不可变的? [英] Why .NET String is immutable?

查看:38
本文介绍了为什么 .NET 字符串是不可变的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

众所周知,String 是不可变的.String 不可变的原因以及引入 StringBuilder 类是可变的吗?

As we all know, String is immutable. What are the reasons for String being immutable and the introduction of StringBuilder class as mutable?

推荐答案

  1. 不可变类型的实例本质上是线程安全的,因为没有线程可以修改它,消除了一个线程以干扰另一个线程的方式修改它的风险(引用本身是另一回事).
  2. 同样,别名不能产生变化(如果 x 和 y 都指向同一个对象,则对 x 的更改会导致对 y 的更改)这一事实允许对编译器进行大量优化.
  3. 还可以进行内存节省优化.实习和雾化是最明显的例子,尽管我们可以做相同原理的其他版本.我曾经通过比较不可变对象并替换对重复项的引用,使它们都指向同一个实例,从而节省了大约半 GB 的内存(耗时,但为了节省大量内存而额外启动一分钟是在有问题的情况下性能获胜).使用无法完成的可变对象.
  4. 将不可变类型作为方法传递给参数不会产生副作用,除非它是 outref(因为它改变了引用,而不是对象).因此,程序员知道如果 string x = "abc" 在方法的开头,并且在方法体中没有改变,那么 x == "abc" 在方法的末尾.
  5. 从概念上讲,语义更像是值类型;尤其是平等基于国家而非身份.这意味着 "abc" == "ab" + "c".虽然这不需要不变性,但对此类字符串的引用在其整个生命周期中始终等于abc"(这确实需要不变性)这一事实使得在保持与先前值的相等性至关重要的情况下用作键,更容易确保正确性of(字符串确实通常用作键).
  6. 从概念上讲,不可变更有意义.如果我们在圣诞节增加一个月,我们并没有改变圣诞节,我们在 1 月下旬产生了一个新的日期.因此 Christmas.AddMonths(1) 产生一个新的 DateTime 而不是改变一个可变的是有道理的.(另一个例子,如果我作为一个可变对象改变我的名字,改变的是我使用的名字,Jon"保持不变,其他 Jons 将不受影响.
  7. 复制既快速又简单,创建一个克隆只需返回.由于无论如何都无法更改副本,因此假装某样东西是它自己的副本是安全的.
  8. .内部状态可以在对象之间安全地共享.例如,如果您正在实现由数组、起始索引和计数支持的列表,那么创建子范围最昂贵的部分就是复制对象.但是,如果它是不可变的,那么子范围对象可以引用同一个数组,只需要更改起始索引和计数,并且非常对构造时间有相当大的改变.
  1. Instances of immutable types are inherently thread-safe, since no thread can modify it, the risk of a thread modifying it in a way that interferes with another is removed (the reference itself is a different matter).
  2. Similarly, the fact that aliasing can't produce changes (if x and y both refer to the same object a change to x entails a change to y) allows for considerable compiler optimisations.
  3. Memory-saving optimisations are also possible. Interning and atomising being the most obvious examples, though we can do other versions of the same principle. I once produced a memory saving of about half a GB by comparing immutable objects and replacing references to duplicates so that they all pointed to the same instance (time-consuming, but a minute's extra start-up to save a massive amount of memory was a performance win in the case in question). With mutable objects that can't be done.
  4. No side-effects can come from passing an immutable type as a method to a parameter unless it is out or ref (since that changes the reference, not the object). A programmer therefore knows that if string x = "abc" at the start of a method, and that doesn't change in the body of the method, then x == "abc" at the end of the method.
  5. Conceptually, the semantics are more like value types; in particular equality is based on state rather than identity. This means that "abc" == "ab" + "c". While this doesn't require immutability, the fact that a reference to such a string will always equal "abc" throughout its lifetime (which does require immutability) makes uses as keys where maintaining equality to previous values is vital, much easier to ensure correctness of (strings are indeed commonly used as keys).
  6. Conceptually, it can make more sense to be immutable. If we add a month onto Christmas, we haven't changed Christmas, we have produced a new date in late January. It makes sense therefore that Christmas.AddMonths(1) produces a new DateTime rather than changing a mutable one. (Another example, if I as a mutable object change my name, what has changed is which name I am using, "Jon" remains immutable and other Jons will be unaffected.
  7. Copying is fast and simple, to create a clone just return this. Since the copy can't be changed anyway, pretending something is its own copy is safe.
  8. . Internal state can be safely shared between objects. For example, if you were implementing list which was backed by an array, a start index and a count, then the most expensive part of creating a sub-range would be copying the objects. However, if it was immutable then the sub-range object could reference the same array, with only the start index and count having to change, with a very considerable change to construction time.

总而言之,对于没有将改变作为其目的的一部分的对象,不可变可能有许多优点.主要的缺点是需要额外的构造,尽管即使在这里它也经常被夸大(请记住,在 StringBuilder 变得比具有其固有构造的等效串联系列更有效之前,您必须进行多次附加).

In all, for objects which don't have undergoing change as part of their purpose, there can be many advantages in being immutable. The main disadvantage is in requiring extra constructions, though even here it's often overstated (remember, you have to do several appends before StringBuilder becomes more efficient than the equivalent series of concatenations, with their inherent construction).

如果可变性是对象目的的一部分(谁希望由工资永远不会改变的 Employee 对象建模),这将是一个缺点,尽管有时即使这样它也很有用(在许多网络中)和其他无状态应用程序一样,执行读取操作的代码与执行更新操作是分开的,并且使用不同的对象可能是很自然的 - 我不会使对象不可变然后强制使用该模式,但如果我已经拥有该模式,我可能会创建我的"read"对象不可变,以保证性能和正确性保证).

It would be a disadvantage if mutability was part of the purpose of an object (who'd want to be modeled by an Employee object whose salary could never ever change) though sometimes even then it can be useful (in a many web and other stateless applications, code doing read operations is separate from that doing updates, and using different objects may be natural - I wouldn't make an object immutable and then force that pattern, but if I already had that pattern I might make my "read" objects immutable for the performance and correctness-guarantee gain).

写时复制是一个中间立场.这里的真实"类持有对状态"类的引用.状态类在复制操作时共享,但如果您更改状态,则会创建状态类的新副本.这比 C# 更常用于 C++,这就是为什么它的 std:string 享有不可变类型的一些(但不是全部)优点,同时保持可变.

Copy-on-write is a middle ground. Here the "real" class holds a reference to a "state" class. State classes are shared on copy operations, but if you change the state, a new copy of the state class is created. This is more often used with C++ than C#, which is why it's std:string enjoys some, but not all, of the advantages of immutable types, while remaining mutable.

这篇关于为什么 .NET 字符串是不可变的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆