为什么我的常量或静态成员没有初始化?

Why is my const or static member not initialized?

我一直在为这个问题摸不着头脑。我怀疑我在这里只是愚蠢,但我似乎无法获得要初始化的 const 或静态成员,因此我可以在整个 class.

中使用它

这是一个说明我的问题(或者更确切地说是我的误解)的例子:

using System;

namespace ConstExample
{
  public class HasImmutableMember
  {
    // static private double fSectionLengthTolerancePerInch = 1 / (20 * 12);  // tolerance is 1" per every 20'
    private const double fSectionLengthTolerancePerInch = 1 / (20 * 12);  // tolerance is 1" per every 20'

    static HasImmutableMember()
    {
      Console.WriteLine("static c'tor: " + fSectionLengthTolerancePerInch);
    }

    public HasImmutableMember()
    {
      Console.WriteLine("instance c'tor: " + fSectionLengthTolerancePerInch);
    }
  }

  public class Program
  {
    public void Main(string[] args)
    {
      HasImmutableMember instance = new HasImmutableMember();
    }
  }
}

控制台输出为:

static c'tor: 0
instance c'tor: 0

不能在const成员声明处设置断点,但如果我使用静态版本,我可以。两者都不能给我我想要的。静态成员声明确实在静态 c'tor 或实例 c'tor 之前被命中。正如预期的那样,静态 c'tor 在实例 c'tor 之前被命中。但是在静态和实例 c'tor 中,我的成员的值是 0 而不是初始化值。

我错过了什么?

原因是有Integer division

When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded.88) If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a.

尝试关注 .

private const double fSectionLengthTolerancePerInch = 1.0 / (20 * 12); 

您需要至少转换一个整数,因为您要除以两个整数,这也会产生一个整数(在您的情况下四舍五入为 0):

private const double fSectionLengthTolerancePerInch = (double)1 / (20 * 12); 

然后你可以使用:

Console.WriteLine("instance c'tor: " + fSectionLengthTolerancePerInch);
>>> 0.00416666666666667

这是一个典型的 "conversion too late" 缺陷,我希望 C# 编译器对此发出警告。您正在对整数进行所有算术运算,然后将结果分配给双精度数。结果是一个整数,整数中的 1 / 240 为零。在双打中做算术:1.0 / 240.0.

我们还看到这个缺陷涉及 non-constants,例如

percentDone = doneSoFar / totalWork;

如果被除数是整数并且结果是双精度数,那么结果很可能是零。

还要注意涉及乘法的相同 "conversion too late" 缺陷:

double microseconds = seconds * 1000000;

如果 seconds 是 int 并且超过几千那么这将溢出整数 before 它分配给 double,而不是你想要的,这是首先转换为 double 并在 double 中进行乘法。同样,应该 1000000.0 向编译器提示您希望以更高的精度完成操作。

您对整数进行运算 1 / (20 * 12)。结果居然是0。您必须至少有一个数字要加倍才能得到加倍的结果:1.0 / (20 * 12).

改变

private const double fSectionLengthTolerancePerInch = 1 / (20 * 12);

private const double fSectionLengthTolerancePerInch = 11.0