为什么静态只读字段不能隐式转换常量?

时间:2018-01-22 10:20:45

标签: c# static constants

鉴于以下代码,我想知道为什么referenceValue = ConstantInt;referenceValue = StaticInt;无法编译时有效。

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. 
        }
    }
}

3 个答案:

答案 0 :(得分:19)

常量在编译时被替换为它们各自的值。因此,从编译器的角度来看,此referenceValue = ConstantInt;与此referenceValue = 42相同。

虽然readonly字段感觉相似,但它们不是。它们的价值在编译时并不是真正知道的。它们由类中的静态字段支持。它们的值可以计算,甚至可以从静态构造函数中修改,因此编译器无法在编译时检查该值是否在uint范围内。

例如:

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
    }
}

修改

正如评论中所指出的,并非所有从常量到变量的赋值都有效,long常量到int变量在没有显式强制转换的情况下不起作用。基于常量的类型,此行为是相同的,无论它是命名常量还是内联常量:

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)

答案 1 :(得分:11)

因为在编译时评估常量字段,所以在运行时评估readonly字段。编译器中的解释器以不同于运行时的方式处理整数。

编译器识别值及其类型,并且可以基于此进行一些基本转换,就像在这种情况下一样。如果您将ConstantInt设置为负数,请尝试查看会发生什么。编译器会出错。将类型更改为longfloat时也是如此:没有编译器转换规则,因此它也会出错。

答案 2 :(得分:2)

来自doc

  

readonly关键字与const关键字不同。 const字段只能在字段声明时初始化。可以在声明或构造函数中初始化只读字段。因此,只读字段可以具有不同的值,具体取决于所使用的构造函数。此外,虽然const字段是编译时常量,但readonly字段可用于运行时常量

     

如下所示:public static readonly uint l1 =(uint)DateTime.Now.Ticks;