在 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.One
、Decimal.Zero
或Decimal.MinusOne
来说,这不是真的,但在C#中,这些都被视为常量。(顺便说一句,String.Empty
在这两种语言中都不被视为常量。
所以我相信这些是作为常量融入语言的(有时,在 VB 的情况下)。
在VB的情况下,它似乎更喜欢加载ReadOnly
值,除了MaxValue
和Minvalue
。(也就是说Const y1 As Decimal = Decimal.One
VB 有效地别名,但在 C# 中真正被视为常量。
顺便说一句,Date.MaxValue
也是ReadOnly
的,但它不被 VB.NET 视为常数(即使它确实有Date
文字)。
更新:我还没有检查最近 VB.NET 或C#的当前结果是什么,但参考源没有特别处理任何Decimal.One
,Decimal.Zero
,Decimal.MinusOne
,Decimal.MaxValue
或Decimal.MinValue
;它们都只是public const
。
我本以为这是为了源代码的可读性
public const Decimal MaxValue = new Decimal(-1, -1, -1, false, (byte) 0);
似乎比幻数更具可读性:
public const Decimal MaxValue = 79228162514264337593543950335m