Why .NET String is immutable? [duplicate] Ask Question

Why .NET String is immutable? [duplicate] Ask Question

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

ベストアンサー1

  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. [編集、私はこれを忘れていました]。内部状態はオブジェクト間で安全に共有できます。たとえば、配列、開始インデックス、カウントで裏付けられたリストを実装している場合、サブ範囲を作成するための最もコストのかかる部分はオブジェクトのコピーになります。ただし、不変であれば、サブ範囲オブジェクトは同じ配列を参照でき、開始インデックスとカウントのみを変更すれば済みます。とても工事期間に大幅な変更がありました。

全体として、変更が目的の一部ではないオブジェクトの場合、不変であることには多くの利点があります。主な欠点は、追加の構成が必要になることですが、ここでも誇張されることがよくあります (StringBuilder が、固有の構成を持つ同等の一連の連結よりも効率的になるには、複数の追加を実行する必要があることに注意してください)。

可変性がオブジェクトの目的の一部である場合 (給与が決して変更されない Employee オブジェクトによってモデル化されることを望む人はいないでしょう)、これは不利になりますが、それでも役に立つ場合もあります (多くの Web およびその他のステートレス アプリケーションでは、読み取り操作を行うコードは更新を行うコードとは別であり、異なるオブジェクトを使用するのは自然なことです。オブジェクトを不変にしてそのパターンを強制することはありませんが、すでにそのパターンがある場合は、パフォーマンスと正確性の保証を向上させるために「読み取り」オブジェクトを不変にするかもしれません)。

コピーオンライトは中間的な立場です。ここでは、「実際の」クラスが「状態」クラスへの参照を保持します。状態クラスはコピー操作で共有されますが、状態を変更すると、状態クラスの新しいコピーが作成されます。これは C# よりも C++ で使用されることが多く、そのため std:string は可変のままで、不変型の利点の一部 (すべてではない) を享受します。

おすすめ記事