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

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

问题描述

大家都知道,字符串是不可改变的。究竟是什么原因的字符串是不可变的和引进的的StringBuilder 类为可变?

解决方案
  1. 不可变类型的实例在本质上是线程安全的,因为没有线程可以修改它,一个线程的方式修改它,干扰其它被删除的风险(引用本身则另当别论)。
  2. 类似地,事实上,混叠不能产生变化(如果x和y都是指一个变化到x蕴涵A变化与y的对象相同)允许可观的编译器的优化。
  3. 节省内存的优化也是可能的。实习和雾化是最明显的例子,虽然我们可以做其他版本相同的原则。有一次,我公司生产的memroy节省约半GB的比较不可变对象和替换引用复制,使它们都指向同一个实例(耗时,但一分钟的额外初创到保存的海量内存量是在本案中的表现赢)。随着中不能做的可变对象。
  4. 无副作用可能来自通过一个不可变的类型作为方法的参数,除非它是退出 REF (因为这改变了参考,不是对象)。因此,一个程序员都知道,如果字符串x =ABC在方法的开始,而不会在方法的身体变化,那么<$ C $ Ç系列> X ==ABC在方法的末尾。
  5. 在概念上,语义更像是值类型;特别是平等是根据状态,而不是同一性。这意味着ABC==AB+C。虽然这并不需要不可改变的事实,引用这样的字符串将始终等于ABC在其整个生命周期(这确实需要不变性),使应用的关键在哪里维护平等previous价值是至关重要的,更容易保证(字符串确实是常用的键)的正确性。
  6. 在概念上,它可以使更多的意义是不可变的。如果我们一个月添加到圣诞节,我们没有改变的圣诞节,我们产生了在一月下旬一个新的日期。这是有道理的,因此该 Christmas.AddMonths(1)产生一个新的的DateTime ,而不是改变一个可变的。 (再比如,如果我作为一个可变对象改变我的名字,是什么改变了这是我用的名字,乔恩保持不变等JONS不会受到影响。
  7. 复制是快速,简单,创造一个克隆返回该。由于副本不能无论如何改变,pretending东西是自己的副本是安全的。
  8. [编辑,我都忘了这一个。内部状态可以对象之间安全地共享。例如,如果您正在实施这实在有赖数组,开始索引和计数,创建一个子范围将复制的对象,那么最昂贵的部分名单。但是,如果它是不可改变的,那么子范围对象可能引用相同的阵列,只有起始索引和计数不得不改变,以非常相当大的变化,以施工时间。

在所有的,对于那些没有发生变化作为其目的之一对象,就不可能有作为不可改变的许多优点。其主要缺点是需要额外的结构,但即使在这里,它经常被夸大了(记住,你必须做一些附加之前的StringBuilder变得比串联等效串联更高效,具有其固有的建筑)。

这将是一个缺点,如果可变性是一个对象(谁愿意要由员工对象,其工资可能永远都不要改变建模)的目的之一,虽然有时即使如此,它可能是有用的(在许多网络等无状态应用程序,code做的读取操作是分开的,这样做的更新,并使用不同的对象可能是自然的 - 我不会让一个对象不变,然后强制该模式,但如果我已经有了这个模式我可能让我的读的对象不可变的性能和正确性,保证收益)。

复制上写是一个中间地带。这里的真正的类包含一个引用状态类。国家类的复制操作的共享,但是如果你改变的状态下,在创建国家一流的新副本。这被更经常使用的C ++比C#,这就是为什么它的性病:串享有一些,但不是全部,不变类型的优点,而其余的可变

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

解决方案

  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 interfers 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 memroy 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. [Edit, I'd forgotten this one]. 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.

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).

It would be a disadvantage if mutability was part of the purpose of an object (who'd want to be modelled 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).

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天全站免登陆