【问题标题】:Why is Chr(3) a constant expression but not Chr(172)?为什么 Chr(3) 是常量表达式而不是 Chr(172)?
【发布时间】:2013-06-04 23:28:36
【问题描述】:

如果我编写以下代码,ReSharper 会建议我将第一个变量 chr3 转换为常量,而不是第二个变量 chr127

Public Class ClassX
    Public Sub SomeMethod()
        Dim chr3 As String = Chr(3)
        Dim chr172 As String = Chr(172)

        Debug.WriteLine(chr3)
        Debug.WriteLine(chr172)
    End Sub
End Class

如果我将两者都转换为常量,我会在 Chr(172) 上收到 Visual Studio 编译器警告,指出“需要常量表达式”,但Chr(3) 没有编译器警告。

Public Class ClassX
    Public Sub SomeMethod()
        Const chr3 As String = Chr(3)
        Const chr172 As String = Chr(172)

        Debug.WriteLine(chr3)
        Debug.WriteLine(chr172)
    End Sub
End Class

是什么让Chr(3) 成为常​​量表达式而不是Chr(172)

【问题讨论】:

  • +1 个有趣的问题。我很确定它与 172 超出标准 ASCII 表有关(它是 7 位,我希望您的问题因此发生在 127 以上的值),但我不知道为什么它会这样打扰编译器。
  • 很好的洞察力。它似乎与 8 位值有关,因为样本值 122 和 127 被接受为常量表达式,但 128 和 172 不是。
  • +1 个有趣的问题

标签: vb.net constants chr


【解决方案1】:

字符 3 是“文本结尾”字符,因此它可能表现出奇怪的行为似乎不足为奇。这个和其他类似的字符很少直接使用。

【讨论】:

    【解决方案2】:

    查看Microsoft.VisualBasic.Strings.Chr() 的源代码,我看到以下内容(我已通过删除异常处理为这篇文章进行了简化):

    /// <summary>
    /// Returns the character associated with the specified character code.
    /// </summary>
    /// 
    /// <returns>
    /// Returns the character associated with the specified character code.
    /// </returns>
    /// <param name="CharCode">Required. An Integer expression representing the code point, or character code, for the character.</param><exception cref="T:System.ArgumentException"><paramref name="CharCode"/> &lt; 0 or &gt; 255 for Chr.</exception><filterpriority>1</filterpriority>
    public static char Chr(int CharCode)
    {
      if (CharCode <= (int) sbyte.MaxValue)
        return Convert.ToChar(CharCode);
    
      Encoding encoding = Encoding.GetEncoding(Utils.GetLocaleCodePage());
      char[] chars1 = new char[2];
      byte[] bytes = new byte[2];
      Decoder decoder = encoding.GetDecoder();
      int chars2;
      if (CharCode >= 0 && CharCode <= (int) byte.MaxValue)
      {
        bytes[0] = checked ((byte) (CharCode & (int) byte.MaxValue));
        chars2 = decoder.GetChars(bytes, 0, 1, chars1, 0);
      }
      else
      {
        bytes[0] = checked ((byte) ((CharCode & 65280) >> 8));
        bytes[1] = checked ((byte) (CharCode & (int) byte.MaxValue));
        chars2 = decoder.GetChars(bytes, 0, 2, chars1, 0);
      }
      return chars1[0];
    }
    

    似乎对于 7 位值,返回 Convert.ToChar(CharCode),我猜编译器足够聪明,可以得出结论是一个常数,而对于 8 位值,当前文化的 CodePage 参与其中,将根据运行代码的计算机给出不同的结果,因此不能是常数。

    更新:我试图在我自己编写的方法中复制这种情况,但不能,这表明编译器本身可能有一个特殊情况规则来评估常量表达式。

    Private Function ConstOrNot(input As Int32) As Int32
        If input = 3 Then Return 7
        Return (New Random).Next
    End Function
    
    Const intC1 As Int32 = ConstOrNot(3)
    

    (也就是说,ConstOrNot() 与调用它的代码存在于同一个程序集中,因此这可能无论如何都不起作用。)

    【讨论】:

      猜你喜欢
      • 2021-10-12
      • 2010-09-23
      • 1970-01-01
      • 1970-01-01
      • 2015-01-17
      • 1970-01-01
      • 2019-11-13
      • 2021-05-10
      • 1970-01-01
      相关资源
      最近更新 更多