'Decimal' source code from Microsoft - will it build?

.net, c#

Solution

There are a few aspects of mscorlib and the like which wouldn't compile as-written, without some interesting hacks. In particular, there are some cyclic dependencies. This is another case, but I think it's reasonable to consider `MaxValue` and `MinValue` as being `const` as far as the C# compiler is concerned.

In particular, it's valid to use them within other `const` calculations:

const decimal Sum = decimal.MaxValue + decimal.MinValue;

The fields have the `DecimalConstantAttribute` applied to them, which is effectively a hack to get around an impedance mismatch between C# and the CLR: you can't have a constant field of type `decimal` in the CLR in the same way that you can have a constant field of type `int` or `string`, with an IL declaration using `static literal ...`.

(This is also why you can't use `decimal` values in attribute constructors - there, the "const-ness" requirement is true IL-level constness.)

Instead, any `const decimal` declaration in C# code is compiled to a `static initonly` field with `DecimalConstantAttribute` applied to it specifying the appropriate data. The C# compiler uses that information to treat such a field as a constant expression elsewhere.

Basically, `decimal` in the CLR isn't a "known primitive" type in the way that `int`, `float` etc are. There are no `decimal`-specific IL instructions.

Now, in terms of the specific C# code you're referring to, I suspect there are two possibilities:

- No, this isn't the exact source code used.

- The C# compiler used to compile mscorlib and other core aspects of the framework may have special flags applied to allow such code, converting it directly to `DecimalConstantAttribute`

To a large extent you can ignore this - it won't affect you. It's a shame that MSDN documents the fields as being `static readonly` rather than `const` though, as that gives the mistaken impression that one can't use them in `const` expressions :(

Problem

I was recently attempting to answer a question that a user posted about why the `decimal` struct does not declare its Min/Max values as `const` like every other numeric primitive; rather, the Microsoft documentation states that it is `static readonly.` In researching that, I dug through the Microsoft source code, and came up with an interesting discovery; the source (.NET 4.5) makes it look like a `const` which is in opposition to what the documentation clearly states (source and relevant struct constructor pasted below). ``` public const Decimal MinValue = new Decimal(-1, -1, -1, true, (byte) 0); public const Decimal MaxValue = new Decimal(-1, -1, -1, false, (byte) 0); public Decimal(int lo, int mid, int hi, bool isNegative, byte scale) { if ((int) scale > 28) throw new ArgumentOutOfRangeException("scale", Environment.GetResourceString("ArgumentOutOfRange_DecimalScale")); this.lo = lo; this.mid = mid; this.hi = hi; this.flags = (int) scale << 16; if (!isNegative) return; this.flags |= int.MinValue; } ``` The thread here continues to unravel, because I can't see how this would compile legally under the rules of C# - because while it still is technically a constant, the compiler thinks it isn't and will give you an error `The expression being assigned to ... must be constant`. Hence what I believe is the reason that the docs call it a `static readonly`. Now, this begs a question: is this file from the Microsoft source server actually the source for decimal, or has it been doctored? Am I missing something?

Original source

Related problems