在C#中,与VB的Asc()和Chr()函数相当的是什么?

35

VB有一些本地函数用于将字符转换为ASCII值,反之亦然 - Asc()和Chr()。

现在我需要在C#中获得相应的功能。最好的方法是什么?


4
请注意,如今很少有人谈论ASCII值。通常,您会使用Unicode代码点(或其UTF-16编码):http://www.joelonsoftware.com/articles/Unicode.html - Joachim Sauer
7
VB.Net的Asc函数不会返回ASCII码,也不会返回Unicode码。它返回当前Windows代码页中的"ANSI"码。 - MarkJ
@MarkJ 这就像VB6一样,想想看! - Tom Blodget
1
如果您需要详细的解释和总结,请查看此问题:C# CHAR FROM INT USED AS STRING, THE REAL EQUIVALENT OF VB CHR() - ib11
12个回答

33

您可以随时添加对 Microsoft.VisualBasic 的引用,然后使用完全相同的方法:Strings.ChrStrings.Asc

这是获得完全相同功能的最简单方法。


4
如果你添加一个引用,它就会存在。 - Samuel
5
与所有其他答案不同,+1 是因为它确实是正确的。他们使用与VB Asc和Chr不同的编码方式,因此是错误的。 - MarkJ
1
@MarkJ:我怀疑AscChr最常见的用途是使用0-126范围内的值,程序员期望将其映射到相应的Unicode代码点;即使有一个系统,例如Chr(34)会产生而不是",我认为编写Chr(34)的程序员可能打算使用" - supercat
这应该是这个问题的被接受的答案。 - Jeff
10
VisualBasic在任何便携式库中都不存在。这将仅在经典的Windows操作系统下运行。 - Maury Markowitz
1
这个解决方案对我不起作用,因为我有一个 .netstandard 库,而 Microsoft.VisualBasic 对于 netstandard 不支持 ASC。 - Johny

26

对于Asc()函数,你可以将char强制转换为int类型,如下所示:

int i = (int)your_char;

对于 Chr(),你可以像这样从 int 转换为 char

char c = (char)your_int;

这是一个演示整个过程的小程序:

using System;

class Program
{
    static void Main()
    {
        char c = 'A';
        int i = 65;

        // both print "True"
        Console.WriteLine(i == (int)c);
        Console.WriteLine(c == (char)i);
    }
}

19
-1是因为这是错误的。 VB.Net的Asc函数 不会 返回ASCII代码,也不会返回Unicode代码。它返回当前Windows代码页(即取决于当前线程的区域设置)中的“ANSI”代码。强制转换将返回一个Unicode代码点。对于大多数语言环境中的大多数字符来说都是不同的。请使用Microsoft.VisualBasic.Strings.Asc和Chr功能。 - MarkJ
1
我必须同意@MarkJ的观点-我尝试了这段代码,对于某些字符(例如a-z),它返回相同的结果,但对于其他字符(“<”等),则返回不同的结果。 - JDB
是的,结果不同: {情况1。Strings.Chr(128) 结果1:8364 '€'} {情况2。(char)128 结果2:128'(一个框值)'} 此外,在第二种情况下,任何大于128的值都会返回“一个框值”,而不是有效字符。 - Sadiq
请查看Garry Shutler的答案,该答案是正确的。 - Jeff
这个答案是不正确的。例如: ?(int)"›"[0] = 8250。 ?Microsoft.VisualBasic.Strings.Asc("›") = 155。 - David

6

我使用了resharper来获得这些信息,确切的代码在您的计算机上以VB运行

/// <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 <paramref name="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) short.MinValue || CharCode > (int) ushort.MaxValue)
    throw new ArgumentException(Utils.GetResourceString("Argument_RangeTwoBytes1", new string[1]
    {
      "CharCode"
    }));
  if (CharCode >= 0 && CharCode <= (int) sbyte.MaxValue)
    return Convert.ToChar(CharCode);
  try
  {
    Encoding encoding = Encoding.GetEncoding(Utils.GetLocaleCodePage());
    if (encoding.IsSingleByte && (CharCode < 0 || CharCode > (int) byte.MaxValue))
      throw ExceptionUtils.VbMakeException(5);
    char[] chars = new char[2];
    byte[] bytes = new byte[2];
    Decoder decoder = encoding.GetDecoder();
    if (CharCode >= 0 && CharCode <= (int) byte.MaxValue)
    {
      bytes[0] = checked ((byte) (CharCode & (int) byte.MaxValue));
      decoder.GetChars(bytes, 0, 1, chars, 0);
    }
    else
    {
      bytes[0] = checked ((byte) ((CharCode & 65280) >> 8));
      bytes[1] = checked ((byte) (CharCode & (int) byte.MaxValue));
      decoder.GetChars(bytes, 0, 2, chars, 0);
    }
    return chars[0];
  }
  catch (Exception ex)
  {
    throw ex;
  }
}


/// <summary>
/// Returns an Integer value representing the character code corresponding to a character.
/// </summary>
/// 
/// <returns>
/// Returns an Integer value representing the character code corresponding to a character.
/// </returns>
/// <param name="String">Required. Any valid Char or String expression. If <paramref name="String"/> is a String expression, only the first character of the string is used for input. If <paramref name="String"/> is Nothing or contains no characters, an <see cref="T:System.ArgumentException"/> error occurs.</param><filterpriority>1</filterpriority>
public static int Asc(char String)
{
  int num1 = Convert.ToInt32(String);
  if (num1 < 128)
    return num1;
  try
  {
    Encoding fileIoEncoding = Utils.GetFileIOEncoding();
    char[] chars = new char[1]
    {
      String
    };
    if (fileIoEncoding.IsSingleByte)
    {
      byte[] bytes = new byte[1];
      fileIoEncoding.GetBytes(chars, 0, 1, bytes, 0);
      return (int) bytes[0];
    }
    byte[] bytes1 = new byte[2];
    if (fileIoEncoding.GetBytes(chars, 0, 1, bytes1, 0) == 1)
      return (int) bytes1[0];
    if (BitConverter.IsLittleEndian)
    {
      byte num2 = bytes1[0];
      bytes1[0] = bytes1[1];
      bytes1[1] = num2;
    }
    return (int) BitConverter.ToInt16(bytes1, 0);
  }
  catch (Exception ex)
  {
    throw ex;
  }
}


/// <summary>
/// Returns an Integer value representing the character code corresponding to a character.
/// </summary>
/// 
/// <returns>
/// Returns an Integer value representing the character code corresponding to a character.
/// </returns>
/// <param name="String">Required. Any valid Char or String expression. If <paramref name="String"/> is a String expression, only the first character of the string is used for input. If <paramref name="String"/> is Nothing or contains no characters, an <see cref="T:System.ArgumentException"/> error occurs.</param><filterpriority>1</filterpriority>
public static int Asc(string String)
{
  if (String == null || String.Length == 0)
    throw new ArgumentException(Utils.GetResourceString("Argument_LengthGTZero1", new string[1]
    {
      "String"
    }));
  return Strings.Asc(String[0]);
}

资源只是存储错误消息的方式,因此您需要找到忽略它们的方法。而另外两种方法,您无法访问,具体如下:

internal static Encoding GetFileIOEncoding()
{
    return Encoding.Default;
}

internal static int GetLocaleCodePage()
{
    return Thread.CurrentThread.CurrentCulture.TextInfo.ANSICodePage;
}

1
谢谢!我看到我需要的代码是Convert.ToChar(CharCode);,我可以在自己的代码中处理检查,而不必导入VB! - HackSlash
我将 Utils.GetFileIOEncoding() 替换为 System.Text.Encoding.Default。 - qtg
Encoding.Default 在 .net Framework 和 .netstandard 2.0 下的工作方式不同。 - Wolfgang Grinfeld
@WolfgangGrinfeld 很不幸,我已经很久没有使用C#和VB了,所以我对现在的许多事情都不了解。 - Hassan Faghihi

3

Strings.Asc不能对超过127的非ASCII字符进行普通的C#转换。我在https://social.msdn.microsoft.com/Forums/vstudio/en-US/13fec271-9a97-4b71-ab28-4911ff3ecca0/equivalent-in-c-of-asc-chr-functions-of-vb?forum=csharpgeneral上找到的答案类似于这样:

    static int Asc(char c)
    {
        int converted = c;
        if (converted >= 0x80)
        {
            byte[] buffer = new byte[2];
            // if the resulting conversion is 1 byte in length, just use the value
            if (System.Text.Encoding.Default.GetBytes(new char[] { c }, 0, 1, buffer, 0) == 1)
            {
                converted = buffer[0];
            }
            else
            {
                // byte swap bytes 1 and 2;
                converted = buffer[0] << 16 | buffer[1];
            }
        }
        return converted;
    }

或者,如果你想要真正的效果,请添加对Microsoft.VisualBasic程序集的引用。


这个函数对我来说是正确的。正如这个答案所指出的那样,强制转换在非 ASCII 字符 127 以外的字符上不起作用。我不建议在你的 C# 项目中引用 VisualBasic 程序集。如果你要这样做,那么你可能还不如创建一个 VB 项目。 - Chris M.
Encoding.Default 在 .NetStandard 2.0 和 .NetFramework 4.x 中的工作方式不同。至少在通过 COM 互操作从 VB6 调用时如此。 - Wolfgang Grinfeld

1

对于 Chr(),您可以使用以下方法:

char chr = (char)you_char_value;

1
在C#中,您可以使用Char.ConvertFromUtf32语句。
int intValue = 65;                                \\ Letter A    
string strVal = Char.ConvertFromUtf32(intValue);

VB的等同于

Dim intValue as integer = 65     
Dim strValue As String = Char.ConvertFromUtf32(intValue) 

不需要 Microsoft.VisualBasic 引用


0

以下程序对于我在 .net standard 2.0 + .net 5 的 COM Interop 服务器环境以及使用代码页为1252的Classic ASP/VB6客户端是有效的。

我尚未测试其在其他代码页上的效果:

   public static int Asc(char String)
    {
        int int32 = Convert.ToInt32(String);
        if (int32 < 128)
            return int32;
        Encoding encoding = CodePagesEncodingProvider.Instance.GetEncoding(Thread.CurrentThread.CurrentCulture.TextInfo.ANSICodePage);
        char[] chars = new char[1] { String };
        if (encoding.IsSingleByte)
        {
            byte[] bytes = new byte[1];
            encoding.GetBytes(chars, 0, 1, bytes, 0);
            return (int)bytes[0];
        }
        byte[] bytes1 = new byte[2];
        if (encoding.GetBytes(chars, 0, 1, bytes1, 0) == 1)
            return (int)bytes1[0];
        if (BitConverter.IsLittleEndian)
        {
            byte num = bytes1[0];
            bytes1[0] = bytes1[1];
            bytes1[1] = num;
        }
        return (int)BitConverter.ToInt16(bytes1, 0);
    }

0

//您可以创建该函数,无需更改您的程序

 private int Chr(int i)
  {
    return (char)i;
  }

感谢Soner Gönül的帮助


0
将此方法添加到C#中。
private  int Asc(char String)
        {
            int int32 = Convert.ToInt32(String);
            if (int32 < 128)
                return int32;
            try
            {
                Encoding fileIoEncoding = Encoding.Default;
                char[] chars = new char[1] { String };
                if (fileIoEncoding.IsSingleByte)
                {
                    byte[] bytes = new byte[1];
                    fileIoEncoding.GetBytes(chars, 0, 1, bytes, 0);
                    return (int)bytes[0];
                }
                byte[] bytes1 = new byte[2];
                if (fileIoEncoding.GetBytes(chars, 0, 1, bytes1, 0) == 1)
                    return (int)bytes1[0];
                if (BitConverter.IsLittleEndian)
                {
                    byte num = bytes1[0];
                    bytes1[0] = bytes1[1];
                    bytes1[1] = num;
                }
                return (int)BitConverter.ToInt16(bytes1, 0);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

`


Encoding.Default 在 netstandard 2.0 中并不总是有效。 - Wolfgang Grinfeld

0

我已经从Microsoft.VisualBasic.dll中提取了Asc()函数:

    public static int Asc(char String)
    {
        int num;
        byte[] numArray;
        int num1 = Convert.ToInt32(String);
        if (num1 >= 128)
        {
            try
            {
                Encoding fileIOEncoding = Encoding.Default;
                char[] str = new char[] { String };
                if (!fileIOEncoding.IsSingleByte)
                {
                    numArray = new byte[2];
                    if (fileIOEncoding.GetBytes(str, 0, 1, numArray, 0) != 1)
                    {
                        if (BitConverter.IsLittleEndian)
                        {
                            byte num2 = numArray[0];
                            numArray[0] = numArray[1];
                            numArray[1] = num2;
                        }
                        num = BitConverter.ToInt16(numArray, 0);
                    }
                    else
                    {
                        num = numArray[0];
                    }
                }
                else
                {
                    numArray = new byte[1];
                    fileIOEncoding.GetBytes(str, 0, 1, numArray, 0);
                    num = numArray[0];
                }
            }
            catch (Exception exception)
            {
                throw exception;
            }
        }
        else
        {
            num = num1;
        }
        return num;
    }

Encoding.Default 在 netstandard 2.0 中并不总是有效。 - Wolfgang Grinfeld

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