Public constant member declared with Const
ID |
vbnet.maintainability.no_public_const_member |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
medium |
Remediation Effort |
low |
Resource |
Api Design |
Language |
VB.NET |
Description
Reports a Public Const member of a class, structure or module, whether the type is stated with
As or inferred from the initializer. Constants declared Private, Friend or Protected,
local constants inside a method, and Public Shared ReadOnly fields - the form this rule asks
for - are not reported.
Rationale
A Const is resolved by the compiler, not at run time: every assembly that reads
HttpClientOptions.MaxRetries gets the literal 3 copied into its own code, and no reference to
the declaring member survives in the compiled output. Publishing one therefore publishes the
value rather than the member. Change it to 5 and rebuild only the declaring assembly, and
callers that were compiled earlier keep using 3 while the declaring code uses 5 - the same
named constant now has two values in one running process, with nothing in either source file to
explain it, and the bug typically appears as sizes or limits disagreeing between components. The
problem is not theoretical: partial rebuilds are what incremental builds, plugin models and
NuGet consumers do by default. A Public Shared ReadOnly field is read through the field at run
time, so updating the declaring assembly updates every caller with no rebuild, and it lifts the
other restrictions of Const as well - the value may be any type, and may be computed in a
shared constructor rather than being limited to a compile-time literal.
The following code illustrates the pattern detected by this rule:
Public Class HttpClientOptions
' FLAGGED: Public constant member declared with Const
Public Const MaxRetries As Integer = 3
' FLAGGED: Public constant member declared with Const
Public Const DefaultUserAgent = "Acme/1.0"
Remediation
Declare the member Public Shared ReadOnly and initialise it in the declaration or in a shared
constructor, so callers read the current value at run time. Keep Const for values that are
genuinely fixed forever and are not part of the published surface - declare those Private or
Friend - and for local constants inside a method, where no other assembly can see them.
' Before: the literal 3 is copied into every calling assembly at compile time
Public Const MaxRetries As Integer = 3
' After
Public Shared ReadOnly MaxRetries As Integer = 3