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

Chr*_*isM 21 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. 
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Tit*_*mir 20

常量在编译时被替换为它们各自的值.因此从编译器的角度来看,这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
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑

正如在注释中指出的那样,并非所有从常量到变量的赋值都可以工作,如果没有显式强制转换,则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)
Run Code Online (Sandbox Code Playgroud)

  • 为了清楚起见,规则是如果值适合,则int常量可以转换为sbyte,byte,short,ushort,uint或ulong,如果适合,则可以将long常量转换为ulong.通常C#不允许这些转换,但它会使已知适合的常量异常.但即使它适合,你也不能把长常数放入int中; 这可能是一个错误,所以C#标记它. (2认同)

Pat*_*man 11

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

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