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

4
如果我写下以下代码,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
+1 有趣的问题。我相当确定它与172在标准ASCII表之外有关(它是7位,因此我预计您的问题会发生在大于127的值),但我不知道为什么它会让编译器感到困扰。 - Niels Keurentjes
很有见地。它似乎与8位值有关,因为样本值122和127被接受为常量表达式,但128和172则不是。 - MCattle
2个回答

1

第三个字符是“文本结束”字符,因此它可能表现出奇怪的行为似乎并不令人惊讶。这个字符和其他类似的字符很少直接使用。


1

查看 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() 存在于调用它的代码所在的同一个程序集中,所以这种方法可能也行不通。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接