Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can constants be implicitly converted while static readonly fields cannot?

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. 
        }
    }
}
like image 602
ChrisM Avatar asked Jan 22 '18 10:01

ChrisM


People also ask

What is the difference between static readonly and constant?

Readonly variable cannot be modified at run-time. It can only be initialized or changed in the constructor. Constant variables cannot be modified after declaration. Static members can be accessed using ClassName.

What is the difference between constant and readonly variable?

const is used to create a constant at compile time. readonly field value can be changed after declaration. const field value cannot be changed after declaration. readonly fields cannot be defined within a method.

Can readonly and const be used interchangeably?

Difference between const and readonlyconst variables can declared in methods ,while readonly fields cannot be declared in methods. const fields cannot be used with static modifier, while readonly fields can be used with static modifier.

Why would you use readonly vs const in C #?

A const is a compile-time constant whereas readonly allows a value to be calculated at run-time and set in the constructor or field initializer. So, a 'const' is always constant but 'readonly' is read-only once it is assigned.

What is the difference between const and static readonly fields?

There is a minor difference between const and static readonly fields in C#.Net. const must be initialized with value at compile time. const is by default static and needs to be initialized with constant value, which can not be modified later on. It can not be used with all datatypes.

Can a readonly field be declared as static in Java?

readonly can be declared as static, but not necessary. No need to initialize at the time of declaration. Its value can be assigned or changed using constructor once. So there is a possibility to change value of readonly field once (does not matter, if it is static or not), which is not possible with const.

What is the difference between readonly and const in C++?

Readonly fields can be initialized at declaration or in the constructor. Therefore, readonly variables are used for the run-time constants. The constant fields must be initialized at the time of declaration. Therefore, const variables are used for compile-time constants.

Can a static readonly variable be changed at compile time?

Static ReadOnly: A Static Readonly type variable's value can be assigned at runtime or assigned at compile time and changed at runtime. But this variable's value can only be changed in the static constructor. And cannot be changed further. It can change only once at runtime. Reference: c-sharpcorner.


3 Answers

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)
like image 107
Titian Cernicova-Dragomir Avatar answered Oct 06 '22 11:10

Titian Cernicova-Dragomir


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.

like image 11
Patrick Hofman Avatar answered Oct 06 '22 12:10

Patrick Hofman


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;

like image 2
Ali Faris Avatar answered Oct 06 '22 10:10

Ali Faris