Decimal.MinValue & Decimal.MaxValue:为什么是静态只读而不是 const 修饰符?



在 C# 中,MinValue字段是为具有以下特征的数值类型定义的:

(1) 十进制类型的静态只读修饰符(链接到 MSDN Libray for .NET 4.5):

public static readonly decimal MinValue

(2) 所有其他数值类型的常量修饰符:

//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

为什么常量修饰符不用于定义十进制.MinValue字段?

备注

(1) 同样的问题适用于数值类型最大值字段。

(2)VB,C++和F#也对十进制类型使用不同的修饰符,因此此问题并非特定于C#语言。

这是一个有趣的问题。我做了一些研究,关于Decimal最小/最大字段的 MS 文档明确指出(请注意,两者的措辞相同;为清楚起见,显示在括号中):

此常量的值为 [负] 79,228,162,514,264,337,593,543,950,335。

以下代码编译没有问题:

public const decimal MaxValue = 79228162514264337593543950335M;

-编辑-

注意:这是 .NET 4.5(从 MS 下载的 PDB 源)源中的字段分配,这是此代码调用的十进制构造函数。请注意,它声明了一个常量值。至少对于 4.5,文档似乎是错误的。(这不是MS文档第一次不正确)。 正如@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;
}

另请注意:在 2.0 框架中,十进制是直接声明的:

public const Decimal MaxValue = 79228162514264337593543950335m;

因此,不一致和不正确的文档是我得出的结论。我将留给其他人查看模式的其他框架版本。

虽然 MSDN 库将十进制MinValue字段描述为static readonly,但 C# 编译器将其视为const

如果MinValue字段是只读的,则以下代码不会编译,但实际上确实可以编译

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

备注

(1) 相同的答案适用于十进制类型MaxValue字段。

(2)有关更多详细信息,Jon Skeet在这里深入了解IL级别的恒定场实现在以下两者之间的差异:

  • 基元数值类型(积分、浮点数和双精度数)和
  • 非基元数字十进制类型。

首先,请注意,从语言的角度来看,这些Decimal值被视为常量(但不是CLR),正如Jon Skeet在回答rmayer06的相关问题时提到的。

(我认为使用ReadOnly而不是Const的原因是,每次使用Const时都不会调用构造函数,除了 :-( )

如果在 C# 或 VB.NET 中编译:x == Decimal.MaxValue,则常量被构造为好像它真的是一个Const

在 VB.NET 中,对于Decimal.OneDecimal.ZeroDecimal.MinusOne来说,这不是真的,但在C#中,这些都被视为常量。(顺便说一句,String.Empty在这两种语言中都不被视为常量。

所以我相信这些是作为常量融入语言的(有时,在 VB 的情况下)。

在VB的情况下,它似乎更喜欢加载ReadOnly值,除了MaxValueMinvalue。(也就是说Const y1 As Decimal = Decimal.OneVB 有效地别名,但在 C# 中真正被视为常量。

顺便说一句,Date.MaxValue也是ReadOnly的,但它被 VB.NET 视为常数(即使它确实有Date文字)。

更新:我还没有检查最近 VB.NET 或C#的当前结果是什么,但参考源没有特别处理任何Decimal.OneDecimal.ZeroDecimal.MinusOneDecimal.MaxValueDecimal.MinValue;它们都只是public const

我本以为这是为了源代码的可读性

public const Decimal MaxValue = new Decimal(-1, -1, -1, false, (byte) 0);

似乎比幻数更具可读性:

public const Decimal MaxValue = 79228162514264337593543950335m

最新更新