c# - 为什么 IsLiteral 对十进制返回 false?

标签 c# reflection decimal constants

以下程序将使用 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;
}

它适用于所有类型,除了 decimal 将返回 false。

谁能解释这种行为?是否有更好的方法来查看字段是否恒定?

最佳答案

运行时的角度来看,它不是常量——因为 CLR 基本上不知道decimal;它不是原始类型。这也是您不能在属性中使用小数的原因。

如果您查看字段的 IL,您可以看到实际操作:

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

请注意其他常量的 IL 确实如何在其中包含 literal,但 DecimalConstant 没有。相反,它只是一个应用了属性的只读字段。该属性允许其他编译器将该字段视为常量并知道该值 - 例如,它可以出现在其他 const 表达式中。

然后有一个类型初始化器在执行时设置字段值:

.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

同样,这仅适用于 DecimalConstant,因为运行时会直接处理其他字段。

关于c# - 为什么 IsLiteral 对十进制返回 false?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51607247/

相关文章:

go - 反射(reflect)类型比较

python - 如何评估字符串输入并检查它是否为小数

c# - 将 Redis 与 C# : value is not an integer or out of range, sPort : 51410, LastCommand 一起使用时出错:

c# - 在 .NET 中解密和检查签名时如何忽略系统存储?

java - 如何避免 Java 中未使用的代码抛出 NoClassDefFoundError

c# - 如何从任何对象属性为 null 或空的列表中删除所有?

java - 格式化十进制数

Python - 关于十进制算术的问题

c# - 如何配置 TeamCity 以同时运行测试而不是一个接一个地运行?

c# - 快速启动简单的 C# FileSystemWatcher Windows 服务