来自Microsoft的'Decimal'源代码-它能构建吗?

5 浏览
0 Comments

来自Microsoft的'Decimal'源代码-它能构建吗?

最近,我试图回答一个用户发布的问题,问题是为什么decimal结构不像其他数值类型那样将其最小/最大值声明为const,而是微软的文档中注明它是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;
}

这个线程的发展情况令人费解,因为根据C#的规则,我无法理解这个代码是如何合法编译的——虽然它仍然是一个常量,但编译器认为它不是常量,并给出一个错误:The expression being assigned to ... must be constant。因此,我相信文档将其称为static readonly的原因就是这个。

现在,这引出了一个问题:这个来自微软源代码服务器的文件是否真的是decimal的源代码,还是被篡改过了?我是不是漏掉了什么?

0
0 Comments

文章标题:微软的'Decimal'源代码会构建吗?

微软的mscorlib和类似的一些方面在不进行一些有趣的黑客技术的情况下不能按原样编译。特别是,存在一些循环依赖关系。这是另一种情况,但我认为从C#编译器的角度来看,将MaxValueMinValue视为const是合理的。

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

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

这些字段应用了DecimalConstantAttribute,这实际上是一种绕过C#和CLR之间的阻抗不匹配的黑客方法:CLR中不能像int或string那样具有类型为decimal的常量字段,使用IL声明使用static literal ...

(这也是为什么不能在属性构造函数中使用decimal值的原因-在那里,“const-ness”要求是真正的IL级别的constness。)

相反,C#代码中的任何const decimal声明都会编译为一个具有应用了DecimalConstantAttributestatic initonly字段,指定适当的数据。C#编译器使用该信息在其他地方将该字段视为常量表达式。

基本上,CLR中的decimal不是像int、float等那样的“已知原始”类型。没有decimal特定的IL指令。

现在,就你提到的具体C#代码而言,我怀疑有两种可能性:

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

在很大程度上,您可以忽略这一点-它不会影响您。但遗憾的是,MSDN将这些字段文档化为static readonly而不是const,这给人们留下了不能在const表达式中使用它们的错误印象:(

这肯定是我考虑的方向,但显然您对.NET的“内部”了解更多。我听说过decimal不是原始类型,但是是什么使其如此?这是由于实现问题吗?

:它在CLR中不是原始类型-例如,typeof(decimal).IsPrimitive返回false。据我所知,CLR对decimal没有任何特殊的了解。

“很遗憾MSDN将这些字段文档化为static readonly”:嗯,许多文档都是基于实际声明的,可以通过反编译器或其他解析器看到。就像在对象浏览器中有时String不被视为sealed,我认为这只是另一个怪癖。

0