38

Is there a difference between having a private const variable or a private static readonly variable in C# (other than having to assign the const a compile-time expression)?

Since they are both private, there is no linking with other libraries. So would it make any difference? Can it make a performance difference for example? Interned strings? Anything similar?

9 Answers 9

37

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.

2
  • 2
    Fortunately of course this won't be an issue for private constants - but it's the most important difference in normal usage.
    – Jon Skeet
    Commented Jan 4, 2009 at 9:39
  • Thanks. I read about the implications to dependent assemblies in the answer to another question. The loading vs. de-referencing is interesting, and so is ldstr. Thanks a lot!
    – Hosam Aly
    Commented Jan 4, 2009 at 9:56
14

Indeed, the two types cannot be changed after they were initialized, but there are some differences between them:

  • 'const' must be initialized where they are declared(at compile time), whereas 'readonly' can be initialized where it is declared or inside the constructor (ar runtime).

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

1
  • Thanks, but my question is more about the side effects than it is about the language constructs themselves.
    – Hosam Aly
    Commented Jan 4, 2009 at 10:27
5

Here are the differences between C# .NET const, readonly and static readonly fields (from this article).

Constants:

  • Static by default
  • Must have compilation-time value (i.e.: you can have "A"+"B" but cannot have method calls)
  • Can be used in attributes
  • Are copied into every assembly that uses them (every assembly gets a local copy of values)
  • Could be declared within functions

Readonly instance fields:

  • Are evaluated when instance is created
  • Must have set value by the time constructor exits

Static readonly fields:

  • Are evaluated when code execution hits class reference (i.e.: new instance is created or static method is executed)
  • Must have evaluated value by the time static constructor is done
  • You really do not want to put ThreadStaticAttribute on these (since static constructor will be executed in one thread only and it will set value for its thread; all other threads will have this value uninitialized)
5

There is notable difference between const and readonly fields in C#.Net

const is by default static and needs to be initialized with constant value, which can not be modified later on. Change of value is not allowed in constructors, too. It can not be used with all datatypes. For ex- DateTime. It can not be used with DateTime datatype.

public const DateTime dt = DateTime.Today;  //throws compilation error
public const string Name = string.Empty;    //throws compilation error
public readonly string Name = string.Empty; //No error, legal

readonly can be declared as static, but not necessary. No need to initialize at the time of declaration. Its value can be assigned or changed using constructor. So, it gives advantage when used as instance class member. Two different instantiation may have different value of readonly field. For ex -

class A
{
    public readonly int Id;

    public A(int i)
    {
        Id = i;
    }
}

Then readonly field can be initialised with instant specific values, as follows:

A objOne = new A(5);
A objTwo = new A(10);

Here, instance objOne will have value of readonly field as 5 and objTwo has 10. Which is not possible using const.

4

Something to note about constants is they're actually stored in your executable, so declaring a lot of them will increase your executable file size.

Normally, this isn't a huge problem, but a friend of mine worked at company that enforced an "everything must be const" rule and managed to significantly increase their compiled executable size.

4
  • Sounds like a DailyWTF story.
    – Jon Limjap
    Commented Jan 4, 2009 at 9:43
  • Well, a no const, all DB approach is definitely worse... I should know. Commented Jan 4, 2009 at 9:53
  • 2
    Believe me, this is only the tip of the iceberg when it comes to weird coding guidelines. Other gems include mandatory else blocks, even if they're empty, and always calling public properties internally.
    – Soviut
    Commented Jan 4, 2009 at 11:27
  • @Stijn It's been so long since I posted this answer that I've forgotten the context. I think I might have been referring to a larger executable versus resource files and the additional time it took to compile one versus the other.
    – Soviut
    Commented Jun 9, 2015 at 22:17
2

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.

2
  • Thanks. But is there absolutely no other difference? Maybe const strings get interned but readonly don't? (I don't know; I'm just asking.)
    – Hosam Aly
    Commented Jan 4, 2009 at 9:31
  • The JIT compiler will intern the readonly variable just like the const. Commented Jan 4, 2009 at 9:46
1

One more thing. I didn't see this in the comments above, although I may have missed it. You cannot create a constant array.

private const int[] values = new int[] { 1, 2, 3 };

But you can create it using a static readonly field.

private static readonly int[] values = new int[] { 1, 2, 3 };

So if you need an array constant, such as a list of allowable values, and an enumeration would not be appropriate, then the static readonly is the only way to go. For instance, if the array were of nullable integers, like this:

private static readonly int?[] values = new int?[] { null, 1, 2, 3 };

Can't do that with a constant, can ya?

1
  • The array itself is not readonly, only the array variable. In other words, values cannot be set to another array, but elements of the array can be manipulated: values[0] = 99 or Array.Sort(values) will both change array values even if it's declared readonly. There is an ImmutableArray type, but that topic goes beyond the basic utility of the const and readonly keywords and strays from the point of the question.
    – C Perkins
    Commented Jun 23, 2022 at 15:25
1

The difference is that the value of a static readonly field is set at run time, and can thus be modified by the containing class, whereas the value of a const field is set to a compile time constant.

In the static readonly case, the containing class is allowed to modify it only

in the variable declaration (through a variable initializer) in the static constructor (instance constructors, if it's not static) static readonly is typically used if the type of the field is not allowed in a const declaration, or when the value is not known at compile time.

Instance readonly fields are also allowed.

Remember that for reference types, in both cases (static and instance) the readonly modifier only prevents you from assigning a new reference to the field. It specifically does not make immutable the object pointed to by the reference.

class Program

{

  public static readonly Test test = new Test();

  static void Main(string[] args)

  {

     test.Name = "Program";

     test = new Test(); // Error: A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)

  }

}

class Test

{

   public string Name;

}

The difference is that static read-only can be modified by the containing class, but const can never be modified and must be initialized to a compile time constant. To expand on the static read-only case a bit, the containing class can only modify it:

-- in the variable declaration (through a variable initializer).

-- in the static constructor (instance constructors if it's not static).


Const Keyword in C# .NET

Example: public const string abc = “xyz”; Initialized only at declaration. Value is evaluated at compile time and can not be changed at run time. An attempt to change it will cause a compilation error. Const is already kind of static. Since classes and structs are initialized at run time with new keyword, you can’t set a constant to a class or structure. But, it has to be one of the integral types. Readonly Keyword in C# .NET

Example: public readonly string abc; Can be initialized in declaration code or consturctor code. Value is evaluated at run time. Can be declared as static or instance level attribute. A read only field can hold a complex object by using the new keyword at run time.

0

Readonly fields can be initialized either at the declaration or in a constructor of a class. Therefore readonly fields can have different values depending on the constructor used.

A readonly member can also be used for runtime constants as in the following example:

public static readonly uint currentTicks = (uint)DateTime.Now.Ticks;

Readonly fields are not implicitly static, and therefore the static keyword can (must) be applied to a readonly field explicitly if required. This is not allowed for const fields, which are implicitly static.

Readonly members can hold complex objects by using the new keyword at initialization.

Not the answer you're looking for? Browse other questions tagged or ask your own question.