c# - 为什么 IsLiteral 对小数返回 false?
问题描述
以下程序将打印字段以及是否使用常量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
is 将返回 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
因为运行时直接处理其他字段而存在。
推荐阅读
- android - 带有 Room 数据库的 Google play 游戏服务
- c - 当第二个输入 b 等于 0 时,如何得到预期的结果?
- java - oracle开发人员中的SQL日期比较
- r - lapply、dplyr 和使用列表中的值
- javascript - 如何在注册页面上添加名称字段?
- c# - 多次加载程序集的语义
- java - 用于删除 Airflow Dag 的 Rest Api 支持
- ios - Flutter 项目 - XCode 构建失败
- image - 将图像转换为 LIst 时出错
飘飘然 - c# - 为什么使用路径中带有空格的文件名通过 cmd 执行 arduino-cli 不起作用?