代码之家  ›  专栏  ›  技术社区  ›  Ira Baxter

C#构造函数中对成员的赋值…不会改变它

  •  0
  • Ira Baxter  · 技术社区  · 7 年前

    我有一个简单的类用来存储缩放积分值 使用成员变量“scaled\u value”(long)和“scale\u factor”。

    我有一个构造函数,它用十进制数填充一个新的类实例 值(尽管我认为值类型是不相关的)。 将出现“缩放的\u值”槽的赋值。。。不会发生。 这个调试.断言以下失败。。。U值为零。

    在立即窗口的断言中断处,我可以使用赋值/检查“比例因子”来检查/设置;它会随着我的设置而改变。

    立即窗口执行的赋值,但它的值

    我正在使用Visual Studio 2017和C#2017。

    这个吃角子老虎机有什么神奇之处?

    public class ScaledLong : Base // handles scaled-by-power-of-ten long numbers
                      // intended to support equivalent of fast decimal arithmetic while hiding scale factors from user
       {
      public long scaled_value; // up to log10_MaxLong digits of decimal precision
      public sbyte scale_factor;  // power of ten representing location of decimal point range -21..+21.  Set by constructor AND NEVER CHANGED.
      public byte byte_size;  // holds size of value in underlying memory array
      string format_string;
    
      <other constructors with same arguments except last value type>
    
      public ScaledLong(sbyte sf, byte size, string format, decimal initial_value)
      {
         scale_factor = sf;
         byte_size = size;
         format_string = format;
    
         decimal temp;
         sbyte exponent;
         {  // rip exponent out of decimal value leaving behind an integer;
        _decimal_structure.value = initial_value;
        exponent = (sbyte)_decimal_structure.Exponent;
        _decimal_structure.Exponent = 0;  // now decimal value is integral
        temp = _decimal_structure.value;
         }
         sbyte sfDelta = (sbyte)(sf - exponent);
         if (sfDelta >= 0)
         {  // sfDelta > 0
        this.scaled_value = 1;
        Debug.Assert(scaled_value == 1);
        scaled_value = (long)Math.Truncate(temp * DecimalTenToPower[sfDelta]);
         }
         else
         {
        temp = Math.Truncate(temp / DecimalHalfTenToPower[-sfDelta]);
        temp += (temp % 2); /// this can overflow for value at very top of range, not worth fixing; note: this works for both + and- numbers (?)
        scaled_value = (long)(temp / 2); // final result
         }
    
      }
    
    0 回复  |  直到 7 年前
        1
  •  0
  •   Ira Baxter    7 年前

    我发现这是通过思考,想知道在地球上一个成员如何可以得到意想不到的方式修改。在我读到@mjwills的评论之前,我找到了解决办法,但他肯定是在找准方向。

    我遗漏了什么(当然!)我刚刚为类编写了一个ToString()方法。。。没有调试。我为什么不说呢?因为它显然不能影响任何东西,所以它不能成为问题的一部分。

    但是,在调试时。。。。调试器可以(在本例中是这样)显示局部变量。为此,它显然会调用ToString()来获得一个好的可显示值。因此,单步执行的行为导致ToSTring()被调用,并且它的错误scratch变量赋值在每次步骤调用之后将插槽归零。

    所以咬我的不是二传手。这可以说是一个令人振奋的消息。(需要时FORTRAN的PURE关键字在哪里?)

    爱因斯坦讨厌远处的怪异行为。程序员讨厌远处的可怕副作用。

    对于调试器调用一个类的ToString()的想法,有人会有点奇怪,因为这个类的构造函数还没有完成。如果构造函数没有完成,关于类状态的哪些断言可以转换为字符串信任?我认为MS调试器应该被修复。有了它,我就可以把时间花在调试ToString上,而不是追求这个。

    谢谢你接受我的问题。它让我找到了答案。