string is a reference type. There are plenty of other immutable types though, and you can create your own: just don't provide any members which change the state! Here's an example:
public class Int32Wrapper { private readonly int value; public int Value { get { return value; } } public Int32Wrapper(int value) { this.value = value; } }
Of course, string also overloads == and !=, overrides Equals and GetHashCode etc... all of which can be done in your own types too.
string does have some genuinely special properties though:
- It's the only reference type for which there's a literal format in IL (and in supporting languages)
- There are IL instructions which specifically use strings
- Other than arrays, string is the only type where the size of the object which varies by instance. (Other types vary depending on the CLR you're using, but for any one CLR, all instances of other types will have the same size - strings and arrays vary by content.)
- If you call
new String(new char[0]) repeatedly, you'll get the same reference every time - It interacts with the interop marshaller in magical ways :)
DateTimeis also an immutable object...