Is there a difference between having a private const
variable or a private static readonly
variable in C# (other than having to assign the co
In use? Not really. Consts are evaluated at compile time, whereas readonly are evaluated at runtime. You can also assign a readonly variable a value in the constructor.
Indeed, the two types cannot be changed after they were initialized, but there are some differences between them:
For example const could be used in this situation:
public class MathValues
{
public const double PI = 3.14159;
}
And readonly would be better for this case:
public class Person
{
public readonly DateTime birthDate;
public Person(DateTime birthDate)
{
this.birthDate = birthDate;
}
}
or
public class Person
{
public readonly DateTime birthDate = new DateTime(1986, 1, 24);
}
'const' is static, so it is shared between all instances of that class and can be accessed directly (like MathValues.PI), whereas 'readonly' is not static. As a consequence a declaration like 'static const' is illegal because const is static, but 'static readonly' is legal
'const' can hold only integral type (sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, or string), an enumeration, or a reference to null (not classes or structures because they are initialized at runtime, with the 'new' keyword), whereas 'readonly' can hold complex types, structures or classes (by using the new keyword at initialization) but cannot hold enumerations
Well, you can use consts in attributes, since they exist as compile time. You can't predict the value of a static readonly variable, since the .cctor
could initialize it from configuration etc.
In terms of usage, constants are burnt into the calling code. This means that if you recompile a library dll to change a public constant, but don't change the consumers, then he consumers will still use the original value. With a readonly variable this won't happen. The flip of this is that constants are (very, very slightly) quicker, since it simply loads the value (rather than having to de-reference it).
Re interning; although you can do this manually, this is most commonly a compiler/runtime feature of literals; if you init a readonly field via a literal:
someField = "abc";
then the "abc"
will be interned. If you read it from config, it won't be. Because a constant string must be a literal, it will also be interned, but it is accessed differently: again, reading from the field is a de-reference, rather than a ldstr.