Why does IsLiteral return false for decimal?

穿精又带淫゛_ 提交于 2019-12-12 10:35:03

问题


The following program will print the fields and whether the are constant or not using IsLiteral

public static class Program
{
    public static void Main(string[] args)
    {
        foreach (var field in typeof(Program).GetFields())
        {
            System.Console.WriteLine(field.Name + " IsLiteral: " + field.IsLiteral);
        }

        System.Console.ReadLine();
    }

    public const decimal DecimalConstant = 99M;
    public const string StringConstant = "StringConstant";
    public const int IntConstant = 1;
    public const double DoubleConstant = 1D;
}

It works correctly for all types, except for decimal is will return false.

Can anyone explain this behavior? And is there a better way to see if a field is constant?


回答1:


It's not a constant from a runtime perspective - because the CLR basically doesn't know about decimal; it's not a primitive type. That's why you can't use decimals in attributes, too.

If you look at the IL for the fields, you can see this in action:

.field public static initonly valuetype [mscorlib]System.Decimal DecimalConstant
.custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor
  (uint8, uint8, uint32, uint32, uint32) =
  (01 00 00 00 00 00 00 00 00 00 00 00 63 00 00 00 00 00) 
.field public static literal string StringConstant = "StringConstant"
.field public static literal int32 IntConstant = int32(0x00000001)
.field public static literal float64 DoubleConstant = float64(1.)

Notice how the IL for the other constants does have literal in it, but DecimalConstant doesn't. Instead, it's just a read-only field with an attribute applied. The attribute allows other compilers to treat the field as a constant and know the value - so it can appear in other const expressions, for example.

There's then a type initializer to set the field value at execution time:

.method private hidebysig specialname rtspecialname static 
        void  .cctor() cil managed
{
  // Code size       13 (0xd)
  .maxstack  8
  IL_0000:  ldc.i4.s   99
  IL_0002:  newobj     instance void [mscorlib]System.Decimal::.ctor(int32)
  IL_0007:  stsfld     valuetype [mscorlib]System.Decimal Program::DecimalConstant
  IL_000c:  ret
} // end of method Program::.cctor

Again, this is only present for DecimalConstant because the runtime handles the other fields directly.



来源:https://stackoverflow.com/questions/51607247/why-does-isliteral-return-false-for-decimal

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!