Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decimal.MinValue & Decimal.MaxValue: why static readonly and not const modifiers?

In C#, MinValue field is defined for numeric types with:

static readonly modifiers for decimal type (Link to MSDN Libray for .NET 4.5):

public static readonly decimal MinValue

const modifier for all other numeric types:

//Integral signed numeric types
public const sbyte MinValue
public const short MinValue
public const int MinValue
public const long MinValue

//Integral unsigned numeric types
public const byte MinValue
public const ushort MinValue
public const uint MinValue
public const ulong MinValue

//Real numeric types
public const float MinValue
public const double MinValue

Why const modifier is not used to define Decimal.MinValue field ?

Remarks:

① Same question applies to numeric types MaxValue field.

② VB, C++ and F# also use different modifiers for decimal type so this question is not specific to C# language.

like image 610
Fabien Launay Avatar asked Feb 01 '14 17:02

Fabien Launay


2 Answers

This is an interesting question. I did some research, and the MS documentation on Decimal Min/Max fields explicitly says (note the wording is the same for both; shown in brackets for clarity):

The value of this constant is [negative] 79,228,162,514,264,337,593,543,950,335.

The following code compiles with no problem:

public const decimal MaxValue = 79228162514264337593543950335M;

- Edit -

Note: here is the assignment of the field from the source for .NET 4.5 (downloaded PDB source from MS), the decimal constructor that is called by this code. Note that it is declaring a const value. It appears, at least for 4.5, that the documentation is wrong. (This would not be the first time MS documentation is incorrect). It also appears that the source code won't compile, as pointed out in a comment by @Daniel.

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;
}

Also note: in the 2.0 framework, decimal is declared outright:

public const Decimal MaxValue = 79228162514264337593543950335m;

So, inconsistency and incorrect documentation is the conclusion I have reached. I will leave it to others to look at the other framework versions for a pattern.

like image 174
theMayer Avatar answered Oct 22 '22 00:10

theMayer


Although MSDN library describes decimal MinValue field as being static readonly, C# compiler treats it as const.

If MinValue field was readonly, following code would not compile, but it actually does compile.

const decimal test = decimal.MinValue - decimal.MinValue;

Remarks:

① Same answer applies to decimal type MaxValue field.

② For further details, Jon Skeet's gives here an insight on how constant field implementation at IL level differs between:

  • Primitive numeric types (integrals, float and double) and
  • The non primitive numeric decimal type.
like image 22
Fabien Launay Avatar answered Oct 21 '22 23:10

Fabien Launay