简体   繁体   English

为什么我的const或static成员未初始化?

[英]Why is my const or static member not initialized?

I've been both scratching and banging my head on this one. 我一直在挠头和撞头。 I suspect I;m just being daft here, but I can't seem to get a const, or static, member to initialize so I can use it throughout a class. 我怀疑我只是在这里呆呆,但是我似乎无法获得const或静态成员进行初始化,因此我可以在整个类中使用它。

Here's an example that demonstrates my problem (or rather my misunderstanding): 这是一个演示我的问题(或更确切地说是我的误解)的示例:

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();
    }
  }
}

Console output is: 控制台输出为:

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

Can't set a breakpoint at the const member declaration, but if I use the static version, I can. 无法在const成员声明中设置断点,但是如果使用静态版本,则可以。 Both fail to give me what I want. 两者都不能给我我想要的东西。 The static member declaration does get hit prior to either the static c'tor or the instance c'tor. 静态成员声明的确在静态c'tor或实例c'tor之前被命中。 And as expected the static c'tor gets hit before the instance c'tor. 正如预期的那样,静态c'tor在实例c'tor之前被命中。 But in both the static and instance c'tor's the value of my member is 0 rather than the initialized value. 但是在静态和实例c'tor中,我的成员的值为0,而不是初始化的值。

What am I missing? 我想念什么?

This is a classic "conversion too late" defect which I wish the C# compiler warned about. 我希望C#编译器发出警告,这是一个经典的“转换为时已晚”的缺陷。 You are doing all the arithmetic in integers, and then assigning the result to a double. 您正在用整数进行所有算术运算,然后将结果分配给double。 The result is an integer, and 1 / 240 in integers is zero. 结果是一个整数,并且1 / 240的整数是零。 Do the arithmetic in doubles: 1.0 / 240.0 . 进行双精度运算: 1.0 / 240.0

We also see this defect involving non-constants, eg, 我们还看到这种涉及非常数的缺陷,例如,

percentDone = doneSoFar / totalWork;

If the dividends are integers and the result is a double then the result is likely to be zero. 如果被除数是整数并且结果是双精度数,则结果很可能为零。

Also watch out for the same "conversion too late" defect involving multiplication: 还要注意涉及乘法的相同“转换为时已晚”缺陷:

double microseconds = seconds * 1000000;

if seconds is int and more than a couple thousand then this will overflow in integers before it assigns to double, instead of what you want, which is to convert to double first and do the multiplication in doubles. 如果seconds是int且超过几千,那么它将在分配给double 之前以整数溢出,而不是您想要的,即先转换为double并进行double乘法。 Again, it should be 1000000.0 to hint to the compiler that you wish the operation to be done in higher precision. 同样,它应该是1000000.0 ,以向编译器提示您希望以更高的精度完成操作。

Reason is that there is Integer division . 原因是存在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. 当整数相除时,/运算符的结果为代数商,其中舍弃了任何小数部分。88)如果商a / b可表示,则表达式(a / b)* b + a%b等于a。

Try following . 尝试跟随。

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

You need to cast at least one of your integers since you are dividing two integers and this results in an integer as well (which gets rounded to 0 in your case): 您需要转换至少一个整数,因为您要除以两个整数,这也会产生一个整数(在您的情况下,该数字会四舍五入为0):

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

And then you can use: 然后您可以使用:

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

You operate on integers 1 / (20 * 12) . 您对整数1 / (20 * 12)进行运算。 The result is actually 0 . 结果实际上是0 You have to have at least one number to be double to get the result as double: 1.0 / (20 * 12) . 您必须至少有一个数字才能加倍以使结果加倍: 1.0 / (20 * 12)

change 更改

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

to

private const double fSectionLengthTolerancePerInch = 11.0

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM