2

I have read about the const and readonly keyowrds in C#. One of the difference between these keywords is that the value of the const is resolved at compile time while readonly keyword is resolved at run time. Though I didn't get chance to implement them in any of my projects. So I thought of giving it a try. I created mylibrary which I would use in my other project. The code in mylibrary is as following

 namespace MyLibrary
 {
  public class Class1
  {
    public static readonly string MyVar = "Vikram";
    //public readonly string MyVar;
    //public Class1()
    //{
    //    MyVar = "Test";
    //}
  }
}

Now I would use this library as reference in my other console project as following

class Program
{
    static void Main(string[] args)
    {
        //MyLibrary.Class1 class1 = new MyLibrary.Class1();
        Console.WriteLine(MyLibrary.Class1.MyVar); // output is vikram
        Console.ReadLine();
        Console.WriteLine(MyLibrary.Class1.MyVar); // changed to Test but still op as  vikram
        Console.ReadLine();
    }
}

Now between these two writeline's I will change the value of "MyVar" in my library and recompile it, according to readonly's concept it should get reflected in the console project without recompiling my main project.

Please correct me if I my understanding of the readonly keyword is wrong.

P.S I have been through the answers of this link. In one of the answers the following is being mentioned

in the case of the readonly value, it is like a ref to a memory location. The value is not baked into AssemblyB's IL. This means that if the memory location is updated, Assembly B gets the new value without recompilation. So if I_RO_VALUE is updated to 30, you only need to build AssemblyA. All clients do not need to be recompiled.

Can anyone please explain what does the bold line exactly means. I think this is what I am doing in my example.

5
  • 1
    What do you mean by "changing the value inbetween the lines"? Commented Aug 3, 2013 at 14:54
  • I suspect it won't be able to recompile the library, because your other program is holding it open
    – doctorlove
    Commented Aug 3, 2013 at 14:55
  • 1
    Recompiling a dependency while a client is executing isn't what I meant.. The bold line means this. Imagine AssemblyDep exposing 2 vars one readonly and the other const and AssemblyClient consuming it. Imagine v1.0 of both assemblies have been deployed on a machine. Now if you want to update the value of the readonly field, you just need to make the change to AssemblyDep, recompile it and deploy it. For the const field, you'd have to build both assemblies and deploy it together. If you deploy just AssemblyDep, the client will continue to use the old 'baked-in' value for the const field. HTH
    – Gishu
    Commented Aug 5, 2013 at 5:37
  • @Gishu - Thanks a ton. Clears my understanding. Never worked on a scenario like this, that's why I had this doubt. But it is clear now.
    – Vikram
    Commented Aug 5, 2013 at 5:50
  • @Gishu - Please add this comment in answers so that I can mark it as answer.
    – Vikram
    Commented Aug 5, 2013 at 6:34

5 Answers 5

3

Your understanding is right, with the exception that you cannot change an assembly that is already loaded. You have to restart the program.

I think you can change a readonly field with reflection. That makes it easier to test this.

Btw, the value of a readonly field must be a runtime value because you can put an arbitrary initializer on it. No way that could be hard-coded by the C# compiler because it cannot know the runtime value statically.

5
  • I'm not sure what you mean by "can": I don't think bypassing readonly after the object is constructed is valid. I do suspect that on at least some versions of .NET Framework (quite possibly the current one too), attempting to do so anyway will have exactly the effect you expect it to have.
    – user743382
    Commented Aug 3, 2013 at 16:35
  • @hvd I'm especially concerned that changing the field breaks in the presence optimizations done by the JIT. I'm not saying that this is a good idea at all... In fact I'd reject code under review based on that.
    – usr
    Commented Aug 3, 2013 at 17:14
  • At the moment, I don't think the JIT can do all that many optimisations, since a method is only JITted once, and has to work regardless of whether the object whose field is being referenced is still under construction. (pastebin.com/N80xTS2w is a valid C# program. f may not be optimised to only read a.i once.) I was more concerned that a future .NET version may be more intelligent and use one version of f for fully constructed objects, and another for the probably usually rare case that the object's readonly fields have not yet been finalised.
    – user743382
    Commented Aug 3, 2013 at 18:07
  • Good points. Is there any comprehensive resource that covers exactly what readonly changes in the optimizer and regarding the memory model? Not that it matters much in practice but I'd be curious to know everything on this topic.
    – usr
    Commented Aug 3, 2013 at 18:35
  • If you dig around, you should be able to find the old 2.0 version of SSCLI (shared source implementation of .NET), allowing you to check the implementation yourself. I'm not aware of any specific documentation on this in any implementation.
    – user743382
    Commented Aug 3, 2013 at 18:49
1

I think that you don't fully understand the meaning of the readonly modifier. Check this reference for information about it.

Please note that the following line:

public static readonly string MyVar = "Vikram";

doesn't mean that each time that you refer to MyVar it's value be re-evaluated.
It just means that once the value of MyVar is set, it won't be changed again, making it readonly for any further use.

e.g., the following lines:

public class Class1
{
    public static readonly string MyVar;

    public Class1()
    {
        MyVar = SomeCalculation();
    }

    Console.WriteLine(MyLibrary.Class1.MyVar);
    Console.WriteLine(MyLibrary.Class1.MyVar);
}

will trigger SomeCalculation() only once !

0

Read Only: Memory is allocated at run time, value is initialised at the run time.

Constant: It uses "const" key word. Value is assigned at the time of declaration. The value will be constant throughout the program. eg. const int i=5;

0

you only need to build AssemblyA. All clients do not need to be recompiled.

There is assembly A and assembly B. Assembly A has the const expression in it somewhere, like:

public const int number = 10;

If this numberis used within assembly B, the compiler will simply put the 'raw' value of the number variable inside the assembly Bs metadata. If number is changed in A, nothing will be changed in B. To make the embedded value change in the assembly B, B has to be recompiled too. One of the benefit of this behavioral, there is no need to load the assembly A to use assembly B.

However, in case of readonly, in this perspective it works like every other (instance|class) fields. It doesn't work like the static way of const (const is considered to be only class level variable, never instance variable)

0

I have written an article after reading a bit about the keywords here on my blog

Some excerpts from the blog Constants

  • provide the value to the const field when it is defined.
  • the compiler then saves the constant's value in the assembly's metadata
  • constants are always considered static members, not instance members.

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