Domanda

If I write the following code, ReSharper will suggest I convert the first variable, chr3 to a constant, but not the second variable, 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

If I convert both to constants, I get a Visual Studio compiler warning on the Chr(172) stating that a "Constant expression is required", but no compiler warning for 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

What makes Chr(3) a constant expression but not Chr(172)?

È stato utile?

Soluzione 2

Looking into the source code for Microsoft.VisualBasic.Strings.Chr(), I see the following (which I've simplified for this post by removing exception handling):

/// <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];
}

It appears to be that for 7-bit values, Convert.ToChar(CharCode) is returned, which I'm guessing the compiler is smart enough to conclude is a constant, whereas for 8-bit values the current culture's CodePage gets involved, which will give different results based on the computer the code runs on, and therefore cannot be a constant.

Update: I've tried to replicate the situation in a method I wrote myself, but cannot, which suggests the compiler itself may have a special case rule for evaluating constant expressions.

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)

(That said, ConstOrNot() exists in the same assembly as the code calling it, so this might not have worked anyway.)

Altri suggerimenti

Character 3 is the "end of text" character so it seems unsurprising that it might exhibit strange behaviour. This, and other similar characters, are rarely used directly.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top