#1,008 – What Happens When You Forget That Strings Are Immutable

Strings in C# (the System.String type) are immutable.  Functions that act upon a string never change the instance of the string, but instead return a new instance of a string.

For example, to replace a portion of a string, you call the Replace method, assigning the result to the original string (or to a new string).

            quote = quote.Replace("Hell", "Minnesota");

If you forget that a string is immutable, you may forget to assign the result of this call to something.  The compiler won’t warn you about this.

            string quote = "Go to Heaven for the climate, Hell for the company.";
            Console.WriteLine(quote);

            // Does NOT change quote.  Rather, it creates
            // a new string, which we don't store anywhere
            quote.Replace("Hell", "Minnesota");

            Console.WriteLine(quote);

The string is not changed, as we might have expected.
1008-001

Advertisement

#801 – An Example of a Simple Immutable Class

You sometimes want to make a class immutable–meaning that you can’t change any instance data in an object after it is created.

Below is an example of a simple class, created using the guidelines for creating an immutable class.

    public class ImmutableDog
    {
        // All properties are read-only
        public string Name { get; private set; }
        public int Age { get; private set; }

        // Return copy of any mutable data
        //   (assuming that DogCollar is mutable)
        private DogCollar collar;
        public DogCollar Collar
        {
            get { return (DogCollar)collar.Clone(); }

            private set
            {
                if (collar != value)
                    collar = value;
            }
        }

        // All data that we need is passed into constructor
        public ImmutableDog(string name, int age, DogCollar collar)
        {
            Name = name;
            Age = age;

            // Make copy of any mutable data passed in
            Collar = (DogCollar)collar.Clone();
        }

        // Methods don't change instance data
        public void DoSomething()
        {
            Console.WriteLine(string.Format("Hi, I'm {0}, aged {1}", Name, Age));
        }
    }

#795 – Rules for Creating an Immutable Class

There are times when it’s desirable to make a class immutable–meaning that client code cannot change any of the class’ data, after an instance of the class is created.

To create an immutable class:

  • Pass all the data that the class requires into a constructor
  • Make a copy of any mutable data type passed into the constructor
  • Make all properties read-only
  • Remove all public fields or make them readonly
  • Ensure that no methods change any of the data in the class
  • Ensure that properties or methods return a copy of any mutable data type that they return
  • Your type should inherit only from another immutable type

#780 – The Case for Immutable structs

You can run into problems when a struct is mutable.  (E.g. when used as a property, in a collection, or when modifying a struct through a method).

You can avoid problems by being careful about how you use the struct and by being aware of value type semantics (you get a copy of the value-typed object, rather than a reference to it).

You can also avoid problems by making your custom structs immutable.  This means:

  • Exposing the data in the struct exclusively through read-only properties
  • Defining methods that modify the value in the struct to return a new instance of the struct

For an example of this, look at the System.DateTime type, which is a struct.  Its properties all have only a get accessor, so you can’t change them.  And methods that change the value of a DateTime, e.g. AddDays, return a new instance of a DateTime.

#69 – Strings Are Immutable

In C#, strings are immutable which means that they cannot be changed after they are created.  More generally, this is the case for the System.String class in .NET.

Syntactically, however, it appears that you can change the contents of a string (e.g. add a character to the end of a string):

 string s1 = "AGORA";
 s1 = s1.Replace('A', 'Z');   // Replace A's with Z's

But in this case, the original string is destroyed, a new string is allocated that contains the result of the replace operation and the s1 variable is set to point to the new string.

In practice, it doesn’t matter much to the programmer that C# strings are internally immutable, since you can “change” them syntactically, as shown above.  Immutability is important only when considering performance of repeated operations on the same string.