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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With