来自微软的"十进制"源代码 - 它会构建吗?

the*_*yer 11 .net c#

我最近试图回答用户发布的关于为什么decimal结构const不像其他所有数字原语一样声明其Min/Max值的问题; 相反,Microsoft文档声明它是static readonly.

在研究中,我挖掘了微软的源代码,并提出了一个有趣的发现; 源代码(.NET 4.5)使它看起来const与文档明确指出的内容相反(源代码和相关的结构构造函数粘贴在下面).

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;
}
Run Code Online (Sandbox Code Playgroud)

这里的线程继续解开,因为我无法看到这将如何在C#的规则下合法编译 - 因为虽然它在技术上仍然是一个常量,但编译器认为它不是并且会给你一个错误The expression being assigned to ... must be constant.因此我认为是文档称之为的原因static readonly.

现在,这引出了一个问题:来自Microsoft源服务器的这个文件实际上是十进制的源,还是已经被修改过了?我错过了什么吗?

Jon*_*eet 20

mscorlib等有几个方面不能编写,没有一些有趣的黑客攻击.特别是,存在一些循环依赖性.这是另一种情况,但我认为这是合理的考虑MaxValueMinValueconst尽可能的C#编译器而言.

特别是,在其他const计算中使用它们是有效的:

const decimal Sum = decimal.MaxValue + decimal.MinValue;
Run Code Online (Sandbox Code Playgroud)

这些字段已经DecimalConstantAttribute应用于它们,这实际上是解决C#和CLR之间阻抗不匹配的问题:你不能在CLR中有一个恒定的字段类型decimal,就像你可以有一个常量字段输入intstring使用IL声明static literal ....

(这也是你不能decimal在属性构造函数中使用值的原因- 那里,"const-ness"要求是真正的IL级constness.)

相反,const decimalC#代码中的任何声明都会编译到一个static initonly字段,并DecimalConstantAttribute应用于该字段,指定相应的数据.C#编译器使用该信息将这样的字段视为其他地方的常量表达式.

基本上,decimal在CLR不处于方式"已知原始的"类型的int,float等都是.没有decimal特定的IL指令.

现在,就您所指的特定C#代码而言,我怀疑有两种可能性:

  • 不,这不是使用的确切源代码.
  • 用于编译mscorlib和框架的其他核心方面的C#编译器可能会应用特殊标志来允许此类代码,将其直接转换为 DecimalConstantAttribute

在很大程度上你可以忽略这一点 - 它不会影响你.令人遗憾的是,MSDN将字段记录为static readonly而不是const,因为这给人以错误的印象,即不能在const表达式中使用它们:(

  • @ rmayer06:就CLR而言,它不是原始的 - 例如,`typeof(decimal).IsPrimitive`返回false.据我所知,CLR对"十进制"没有任何特殊的了解. (2认同)