开发者

What is the difference between a mutable and immutable string in C#?

What is the difference between a mutable and imm开发者_运维知识库utable string in C#?


Mutable and immutable are English words meaning "can change" and "cannot change" respectively. The meaning of the words is the same in the IT context; i.e.

  • a mutable string can be changed, and
  • an immutable string cannot be changed.

The meanings of these words are the same in C# / .NET as in other programming languages / environments, though (obviously) the names of the types may differ, as may other details.


For the record:

  • String is the standard C# / .Net immutable string type
  • StringBuilder is the standard C# / .Net mutable string type

To "effect a change" on a string represented as a C# String, you actually create a new String object. The original String is not changed ... because it is unchangeable.

In most cases it is better to use String because it is easier reason about them; e.g. you don't need to consider the possibility that some other thread might "change my string".

However, when you need to construct or modify a string using a sequence of operations, it may be more efficient to use a StringBuilder. An example is when you are concatenating many string fragments to form a large string:

  • If you do this as a sequence of String concatenations, you copy O(N^2) characters, where N is the number of component strings.
  • If use a StringBuilder you only copy O(N) characters.

And finally, for those people who assert that a StringBuilder is not a string because it is not immutable, the Microsoft documentation describes StringBuilder thus:

"Represents a mutable string of characters. This class cannot be inherited."


String is immutable

i.e. strings cannot be altered. When you alter a string (by adding to it for example), you are actually creating a new string.

But StringBuilder is not immutable (rather, it is mutable)

so if you have to alter a string many times, such as multiple concatenations, then use StringBuilder.


An object is mutable if, once created, its state can be changed by calling various operations on it, otherwise it is immutable.

Immutable String

In C# (and .NET) a string is represented by class System.String. The string keyword is an alias for this class.

The System.String class is immutable, i.e once created its state cannot be altered.

So all the operations you perform on a string like Substring, Remove, Replace, concatenation using '+' operator etc will create a new string and return it.

See the following program for demonstration -

string str = "mystring";
string newString = str.Substring(2);
Console.WriteLine(newString);
Console.WriteLine(str);

This will print 'string' and 'mystring' respectively.

For the benefits of immutability and why string are immutable check Why .NET String is immutable?.

Mutable String

If you want to have a string which you want to modify often you can use the StringBuilder class. Operations on a StringBuilder instance will modify the same object.

For more advice on when to use StringBuilder refer to When to use StringBuilder?.


All string objects are immutable in C#. Objects of the class string, once created, can never represent any value other than the one they were constructed with. All operations that seem to "change" a string instead produce a new one. This is inefficient with memory, but extremely useful with regard to being able to trust that a string won't change out form under you- because as long as you don't change your reference, the string being referred to will never change.

A mutable object, by contrast, has data fields that can be altered. One or more of its methods will change the contents of the object, or it has a Property that, when written into, will change the value of the object.

If you have a mutable object- the most similar one to String is StringBuffer- then you have to make a copy of it if you want to be absolutely sure it won't change out from under you. This is why mutable objects are dangerous to use as keys into any form of Dictionary or set- the objects themselves could change, and the data structure would have no way of knowing, leading to corrupt data that would, eventually, crash your program.

However, you can change its contents- so it's much, much more memory efficient than making a complete copy because you wanted to change a single character, or something similar.

Generally, the right thing to do is use mutable objects while you're creating something, and immutable objects once you're done. This applies to objects that have immutable forms, of course; most of the collections don't. It's often useful to provide read-only forms of collections, though, which is the equivalent of immutable, when sending the internal state of your collection to other contexts- otherwise, something could take that return value, do something to it, and corrupt your data.


Immutable :

When you do some operation on a object, it creates a new object hence state is not modifiable as in case of string.

Mutable

When you perform some operation on a object, object itself modified no new obect created as in case of StringBuilder


In .NET System.String (aka string) is a immutable object. That means when you create an object you can not change it's value afterwards. You can only recreate a immutable object.

System.Text.StringBuilder is mutable equivalent of System.String and you can chane its value

For Example:

class Program
{
    static void Main(string[] args)
    {

        System.String str = "inital value";
        str = "\nsecond value";
        str = "\nthird value";

        StringBuilder sb = new StringBuilder();
        sb.Append("initial value");
        sb.AppendLine("second value");
        sb.AppendLine("third value");
    }
}

Generates following MSIL : If you investigate the code. You will see that whenever you chane an object of System.String you are actually creating new one. But in System.Text.StringBuilder whenever you change the value of text you dont recreate the object.

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       62 (0x3e)
  .maxstack  2
  .locals init ([0] string str,
           [1] class [mscorlib]System.Text.StringBuilder sb)
  IL_0000:  nop
  IL_0001:  ldstr      "inital value"
  IL_0006:  stloc.0
  IL_0007:  ldstr      "\nsecond value"
  IL_000c:  stloc.0
  IL_000d:  ldstr      "\nthird value"
  IL_0012:  stloc.0
  IL_0013:  newobj     instance void [mscorlib]System.Text.StringBuilder::.ctor()
  IL_0018:  stloc.1
  IL_0019:  ldloc.1
  IL_001a:  ldstr      "initial value"
  IL_001f:  callvirt   instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
  IL_0024:  pop
  IL_0025:  ldloc.1
  IL_0026:  ldstr      "second value"
  IL_002b:  callvirt   instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::AppendLine(string)
  IL_0030:  pop
  IL_0031:  ldloc.1
  IL_0032:  ldstr      "third value"
  IL_0037:  callvirt   instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::AppendLine(string)
  IL_003c:  pop
  IL_003d:  ret
} // end of method Program::Main


Strings are mutable because .NET use string pool behind the scene. It means :

string name = "My Country";
string name2 = "My Country";

Both name and name2 are referring to same memory location from string pool. Now suppose you want to change name2 to :

name2 = "My Loving Country";

It will look in to string pool for the string "My Loving Country", if found you will get the reference of it other wise new string "My Loving Country" will be created in string pool and name2 will get reference of it. But it this whole process "My Country" was not changed because other variable like name is still using it. And that is the reason why string are IMMUTABLE.

StringBuilder works in different manner and don't use string pool. When we create any instance of StringBuilder :

var address  = new StringBuilder(500);

It allocate memory chunk of size 500 bytes for this instance and all operation just modify this memory location and this memory not shared with any other object. And that is the reason why StringBuilder is MUTABLE.

I hope it will help.


None, actually. The String class is mutable.

unsafe
{
    string foo = string.Copy("I am immutable.");
    fixed (char* pChar = foo)
    {
        char* pFoo = pChar;

        pFoo[5] = ' ';
        pFoo[6] = ' ';
    }

    Console.WriteLine(foo); // "I am   mutable."
}

This kind of logic is done all the time in the String and StringBuilder classes, actually. They just allocate a new string each time you call Concat, Substring, etc. and use pointer arithmetic to copy over to the new string. Strings just don't mutate themselves, hence why they are considered "immutable".


By the way, do not attempt this with string literals or you will badly mess up your program:

string bar = "I am a string.";

fixed (char* pChar = bar)
{
    char* pBar = pChar;

    pBar[2] = ' ';
}

string baz = "I am a string.";

Console.WriteLine(baz); // "I  m a string."

This is because string literals are interned in the desktop .NET Framework; in other words, bar and baz point to the exact same string, so mutating one will mutate the other. This is all fine and dandy though if you're using an unmanaged platform like WinRT, which lacks string interning.


The data value may not be changed. Note: The variable value may be changed, but the original immutable data value was discarded and a new data value was created in memory.


To clarify there is no such thing as a mutable string in C# (or .NET in general). Other langues support mutable strings (string which can change) but the .NET framework does not.

So the correct answer to your question is ALL string are immutable in C#.

string has a specific meaning. "string" lowercase keyword is merely a shortcut for an object instantiated from System.String class. All objects created from string class are ALWAYS immutable.

If you want a mutable representation of text then you need to use another class like StringBuilder. StringBuilder allows you to iteratively build a collection of 'words' and then convert that to a string (once again immutable).


in implementation detail.

CLR2's System.String is mutable. StringBuilder.Append calling String.AppendInplace (private method)

CLR4's System.String is immutable. StringBuilder have Char array with chunking.


From http://yassershaikh.com/what-is-the-difference-between-strings-and-stringbuilder-in-c-net/

Short Answer : String is immutable – whereas StringBuilder is mutable.

What does that mean ? Wiki says : In object-oriented, an immutable object is an object whose state cannot be modified after it is created. This is in contrast to a mutable object, which can be modified after it is created.

From the StringBuilder Class documentation:

The String object is immutable. Every time you use one of the methods in the System.String class, you create a new string object in memory, which requires a new allocation of space for that new object.

In situations where you need to perform repeated modifications to a string, the overhead associated with creating a new String object can be costly.

The System.Text.StringBuilder class can be used when you want to modify a string without creating a new object. For example, using the StringBuilder class can boost performance when concatenating many strings together in a loop.


Here is the example for Immutable string and Mutable string builder

        Console.WriteLine("Mutable String Builder");
        Console.WriteLine("....................................");
        Console.WriteLine();
        StringBuilder sb = new StringBuilder("Very Good Morning");
        Console.WriteLine(sb.ToString());
        sb.Remove(0, 5);
        Console.WriteLine(sb.ToString());

        Console.WriteLine();

        Console.WriteLine("Immutable String");
        Console.WriteLine("....................................");
        Console.WriteLine();
        string s = "Very Good Morning";
        Console.WriteLine(s);
        s.Substring(0, 5);
        Console.WriteLine(s);
        Console.ReadLine();


String in C# is immutable. If you concatenate it with any string, you are actually making a new string, that is new string object ! But StringBuilder creates mutable string.


StringBuilder is a better option to concat a huge data string because the StringBuilder is a mutable string type and StringBuilder object is an immutable type, that means StringBuilder never create a new instance of object while concat the string.

If we are using string instead of StringBuilder to achieve for concatenation then it will create new instance in memory every time.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜