Reputation: 1168
Given the below code, I wonder why referenceValue = ConstantInt;
is valid while referenceValue = StaticInt;
fails to compile.
namespace Demo
{
public class Class1
{
private const int ConstantInt = 42;
private static readonly int StaticInt = 42;
public void DemoMethod(ref uint referenceValue)
{
referenceValue = ConstantInt; // This compiles
referenceValue = StaticInt; // This claims that the source type 'int' cannot be converted to 'unit' implicitly.
}
}
}
Upvotes: 22
Views: 1857
Reputation: 249686
Constants are replaced at compile time with their respective value. So from the compiler perspective this referenceValue = ConstantInt;
is the same as this referenceValue = 42
.
While readonly
fields feel similar, they are not. Their value is not truly known at compile time. They are backed by a static field on the class. Their value can be computed, even modified from a static constructor, so the compiler can't check that the value is within the range of uint
at compile time.
For example:
public class Class1
{
private const int ConstantInt = 42;
private static readonly int StaticInt = 42;
static Class1()
{
StaticInt = -20;
}
public void DemoMethod(ref uint referenceValue)
{
referenceValue = StaticInt; // it's -20
}
}
Edit
As pointed out in the comments not all assignments from constants to variables work, long
constant to int
variable does not work without an explicit cast. This behavior is the same based on the type of the constant, regardless of whether it is a named constant or an inline constant:
private const long ConstantInt = 42;
// Both of these will cause an error:
referenceValue = ConstantInt; // can't be converted implicitly
referenceValue = 42L; // but neither can an inline long constant (the L makes it long)
Upvotes: 20
Reputation: 18602
from the doc
The readonly keyword is different from the const keyword. A const field can only be initialized at the declaration of the field. A readonly field can be initialized either at the declaration or in a constructor. Therefore, readonly fields can have different values depending on the constructor used. Also, while a const field is a compile-time constant, the readonly field can be used for runtime constants
as in this line: public static readonly uint l1 = (uint)DateTime.Now.Ticks;
Upvotes: 2
Reputation: 156978
Because constant fields are evaluated on compile time, while readonly
fields are evaluated on run time. The interpreter in the compiler treats your integers differently than the runtime does.
The compiler recognizes the value and its type and it can do some basic conversion based on that, as it does in this case. Try and see what happens if you set ConstantInt
to a negative number. The compiler will error out. The same is true when you change the type to long
or float
: there is no compiler conversion rule, so it errors out too.
Upvotes: 11