I use SonarQube to analyze my C# code and I like it. It even gives really good hints about things I didn’t know about C#. But there are two rules about using constant
and static readonly
properties and fields that I am quite confused because it seems they are in conflict with each other. Again, I will write a blog post to figure out that and learn it. This is a continuation of the previous blog post (C#: Difference of Properties and Fields).
Public constant members should not be used
This is SonarQube’s rule S2339 and its severity is even critical. Practically this means that public constant fields and properties should be static readonly
and not const
:
public static readonly string StaticReadonlyField = "static readonly"; // this is OK (#1) public const string ConstField = "const"; // this is not OK (#2)
What makes #2 not OK? It is tricky pitfall which is rare but better not to use it because consequences can be fatal. That is the reason it has critical severity in SonarQube. Here is a diagram that illustrates this pitfall:

In the example above MyAssemblyB.dll took the value of MyAssemblyA.Version when MyAssemblyB.dll was compiled. And after that MyAssemblyA was updated to version 2.0 and compiled, but MyAssemblyB wasn’t compiled. MyAssemblyB thought that MyAssembly.Version was still “1.0” even if its value was changed to “2.0”. Here is the reason for this:
Constant members are copied at compile time to the call sites, instead of being fetched at runtime. (SonarQube rule S2339)
So you shouldn’t use public constant members. Prefer static readonly
members. Note that this doesn’t mean you can’t use private or protected constant members or constant variables. This only applies to public constant members. So prefer these:
public static string Version; // static property which has only a getter { get { return "2.0"; } } public static readonly string Version = "2.0"; // static readonly field
Static readonly constants should be const instead
This is SonarQube’s rule S3962. But unlike previous rule, this has only minor severity. Confusing with this rule is that it practically says just opposite than the previous rule: don’t use static readonly
. Here is an example:
public class MyExample { private static readonly int x = 1; // this is not OK (#1) private const readonly int y = 2; // this is OK (#2) public static readonly double MainVersion = 1.0; // this is not OK (#3) public const double SubVersion = 1.1; // this is OK (#4) }
Reason to prefer const
is performance. Because const
is calculated at compile time and static readonly
at runtime it makes const
slightly faster. Maybe this doesn’t practically matter to your program’s performance but it is a good practice.
What then makes me confuse with this rule? It is “#3 vs #4”. The previous rule just said that #3 is OK and #4 is not OK when here it is opposite of it. What should I do if I have a public constant value? They are even quite common. Public constant fields are quite risky (remember its severity: critical) but here severity is only a minor. Maybe in the future, I will use properties instead of #3 and #4:
public static double MainVersion; // #3 { get { return 1.0; } } public static double SubVersion; // #4 { get { return 1.1; } }
Conclusion
- Don’t use public constant members
- Instead use public static properties with getter only
- When private or protected member or variable prefer `const` over `static readonly` because it is more efficient
public MyClass GoodConstantMembers { public static string Version // public, use static read-only { get { return "1.0"; } } private const int x = 4; // non-public, use const public void MyMethod() { int const name = "xxx"; // variable, use const ... } }