10

Today I found an article where a const field is called compile-time constant while a readonly field is called runtime constant. The two phrases come from 《Effective C#》. I searched in MSDN and the language spec, find nothing about runtime constant.

No offensive but I don't think runtime constant is a proper phrase.

private readonly string foo = "bar";

creates a variable named "foo", whose value is "bar", and the value is readonly, here it is a variable, no business on constant. A readonly variable is still a variable, it can't be a constant. Variable and constant are mutually exclusive.

Maybe this question goes overboard, still I want to listen to others' opinions. What do you think?

8
  • 5
    readonly is poor name. It should have been called immutable.
    – leppie
    Commented Jul 4, 2012 at 6:39
  • 1
    I agree that this is not a good choice of terminology in the book. This question, though, is not a good fit for SO because practical, answerable questions based on actual problems that you face. Chatty, open-ended questions diminish the usefulness of our site and push other questions off the front page
    – Eric J.
    Commented Jul 4, 2012 at 6:39
  • It's a "constant" in that it's a value which doesn't and can't change (reflection aside). It's not a constant expression in the C# specification terminology, but I don't think that's much of a problem when this is being described in a book. It really doesn't sound like you've got a programming question here...
    – Jon Skeet
    Commented Jul 4, 2012 at 6:39
  • @JonSkeet: Technically the value can change during the execution of static constructors, can it not?
    – Eric J.
    Commented Jul 4, 2012 at 6:40
  • 2
    The IL terminology is quite nice here: initonly Commented Jul 4, 2012 at 6:58

5 Answers 5

10

I believe that author means the following:

Consider example:

public class A {

     public const int a = Compute();         

     private static int Compute(){

          /*some computation and return*/ 
          return some_computed_value;
     }
}

this, will not compile, as you have to have constant value to assign to a . So this is a meaning of compile-time constant .

Instead if you change this to

public class A {

     public readonly int a = Compute();          

     private static int Compute(){
          /*some computation and return*/ 
          return some_computed_value;
     }
}

this will compile. It at runtime makes a computation and assign it to a. This is a meaning of runtime constant

2
  • But it's not a constant, it's a variable...it's just..you can't change its value after initialization.
    – Cheng Chen
    Commented Jul 4, 2012 at 6:56
  • 3
    @DannyChen: as others pointed out I believe the book is talking about constant (not changable) value. In first time is becomes such at compile time, in second case it becomes at runtime (after computation).
    – Tigran
    Commented Jul 4, 2012 at 6:58
6

As you yourself note, that term is not used in the language specification etc. So; blame that book! I would call it a "readonly field", because that is what it is - where the definition of "readonly" here relates to the initializer/constructor, and is limited to regular code. For example, even readonly fields are changeable...

// how to annoy your colleagues...
typeof(string).GetField("Empty").SetValue(null, " ");

(Note, this no longer works on recent CLR versions - the JIT presumably replaces the field-load with a ldstr - but it genuinely did for a very long time)

(more genuine reasons to do this on objects relate to deserialization)

5
  • I never call it "**** constant",ok...blame the book!
    – Cheng Chen
    Commented Jul 4, 2012 at 6:52
  • 3
    @Danny when I say "blame the book", I think Jon's point is a good one; perhaps it is simply not making it clear when it is using descriptive rather than formal terminology Commented Jul 4, 2012 at 6:54
  • @Jacek unfortunately this no longer works in recent CLRs - I think the JIT detects string.Empty and jumps directly to "ldstr" instead of loading the static field Commented Jan 25, 2014 at 11:14
  • You can still change instance readonlys. Not static ones though.
    – Bitterblue
    Commented Apr 14, 2014 at 12:38
  • @mini-me oh, you can still change static readonly fields. The problem I am highlighting is that in 4.5 (?) onwards, the JIT rewrites string.Empty completely - it never ever ever actually looks at the field (except when using reflection, which doesn't use the JIT) Commented Apr 14, 2014 at 13:57
2

A readonly variable can only be changed in its constructor and can be used on complex objects. A constant variable cannot be changed at runtime, but can only be used on simple types like Int, Double, String. Runtime constant is somewhat accurate, but confuses the issue, there are very explicit differences between a constant and a readonly, and so naming one similar to another is probably not a good idea, even though often they are used to the same purpose.

A quick summary of the differences here

2

I would call readonly a "write once variable", which is checked by the compiler, not at runtime. You could write the field using reflection, so it is not constant at runtime.

4
  • Isn't a readonly variable checked at runtime, not at compile time?
    – Ryan Amies
    Commented Jul 4, 2012 at 6:42
  • No, it can be written at runtime. This is done by serializers, NHibernate etc. Commented Jul 4, 2012 at 6:44
  • @Marc: yeah ... you could also call it "write-only-in-constructor-or-field-initializer-variable". I mean, it's getting stupid, isn't it? Commented Jul 4, 2012 at 6:54
  • 3
    @StefanSteinegger I believe the IL term would work well: initonly; that's also the term used in cpp/CLR Commented Jul 4, 2012 at 6:55
2

const vs readonly

This a complete resume comparison between const and readonly:

|-----------------------------------------|-----------------------------------------|
|              Constant Field             |             Read-only Field             |
|-----------------------------------------|-----------------------------------------|
| Compile-time constant                   | Run-time constant                       |
|-----------------------------------------|-----------------------------------------|
| Assigned to an expression evaluated at  | Assigned to any valid expression at     |
| compile time                            | runtime                                 |
|-----------------------------------------|-----------------------------------------|
| Assigned on declaration                 | Assigned on declaration or constructor  |
|-----------------------------------------|-----------------------------------------|
| Only number, Boolean or string          | Any data type                           |
|-----------------------------------------|-----------------------------------------|
| Always static                           | Optionally static                       |
|-----------------------------------------|-----------------------------------------|

Explanation

  • Constants are static (no need to instantiate the class to access them).
  • Constants can only be assigned on declaration.
  • Constants are compile-time constant because they are assigned to an expression evaluated at compile time: when they changed, the project should be recompiled to use the new values.
  • Read-Only Fields are variables in a class which hold a value that is initialized (only in the constructor or in the declaration) and then not changed.
  • Read-Only Fields are Runtime constant because they can be assigned to any valid expression at runtime.
  • A Read-Only Field apply to the instance of the object but not the property of that instance. So other code can change the instance property of read-only field.
  • Read-Only Fields are optionally static (if you want to make them shared by all instances).

When to use const and when to use readonly ?

  • Constants are useful when they are of simple type and their values will never be changed.
  • Read-Only Fields are useful when they are initialized from a source (file, database or other codes, ..etc.) but then they will not be changed.

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