35

VB has a couple of native functions for converting a char to an ASCII value and vice versa - Asc() and Chr().

Now I need to get the equivalent functionality in C#. What's the best way?

4

12 Answers 12

34

You could always add a reference to Microsoft.VisualBasic and then use the exact same methods: Strings.Chr and Strings.Asc.

That's the easiest way to get the exact same functionality.

6
  • 4
    If you add a reference, it will exist.
    – Samuel
    Commented Apr 6, 2009 at 12:50
  • 5
    +1 For actually being right, unlike all the other answers. They use different encodings from VB Asc and Chr and are wrong.
    – MarkJ
    Commented Oct 26, 2012 at 22:06
  • 1
    @MarkJ: I suspect most common uses of Asc and Chr use values in the range 0-126, which the programmer would expect to map to the corresponding Unicode code points; even if there were a system where, e.g., Chr(34) would yield rather than ", I would think the programmer who wrote Chr(34) probably intended ".
    – supercat
    Commented Oct 26, 2012 at 23:20
  • 10
    VisualBasic does not exist in any of the portable libraries. This will work only under classic Windows OS's. Commented Sep 17, 2015 at 17:24
  • 1
    This solution doesn't work for me as I have a .netstandard lib and Microsoft.VisualBasic for netstandard doesn't support ASC
    – Johny
    Commented Dec 9, 2019 at 20:19
27

For Asc() you can cast the char to an int like this:

int i = (int)your_char;

and for Chr() you can cast back to a char from an int like this:

char c = (char)your_int;

Here is a small program that demonstrates the entire thing:

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);
    }
}
5
  • 20
    -1 because this is wrong. VB.Net Asc doesnt return ASCII codes, nor does it return Unicode codes. It returns "ANSI" codes in the current Windows code page (i.e. depends on current thread's locale). The cast will return a Unicode code point. Different for most characters on most locales. Use Microsoft.VisualBasic.Strings.Asc and Chr.
    – MarkJ
    Commented Oct 26, 2012 at 21:58
  • 1
    I have to agree with @MarkJ - I tried this code and it returns the same results for some characters (a-z, for example) but different results for others ("<", etc.).
    – JDB
    Commented Nov 16, 2012 at 21:00
  • Yes, results are not same: {case 1. Strings.Chr(128) result 1: 8364 '€'} { case 2. (char) 128 result 2: 128 '(a box value) '} Besides, in 2nd case any value greater than 128 returns 'a box value' instead of a valid character.
    – Sadiq
    Commented Mar 27, 2015 at 9:45
  • Please see Garry Shutler's answer below which is correct.
    – Jeff
    Commented Apr 14, 2015 at 15:37
  • Is not wright this answer. For example: ?(int)"›"[0] = 8250. ?Microsoft.VisualBasic.Strings.Asc("›") = 155.
    – David
    Commented Apr 11, 2023 at 10:46
6

I got these using resharper, the exact code runs by VB on your machine

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

Resources are just stored error message, so somehow the way you want ignore them, and the other two method which you do not have access to are as follow:

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

internal static int GetLocaleCodePage()
{
    return Thread.CurrentThread.CurrentCulture.TextInfo.ANSICodePage;
}
4
  • 1
    Thanks! I see the line I need is Convert.ToChar(CharCode); and I can handle the checking in my own code instead of importing VB!
    – HackSlash
    Commented May 8, 2018 at 19:24
  • I replace Utils.GetFileIOEncoding() with System.Text.Encoding.Default
    – qtg
    Commented Dec 22, 2020 at 0:55
  • Encoding.Default works differently under .net Framework vs .netstandard 2.0 Commented Jun 3, 2021 at 11:48
  • @WolfgangGrinfeld Unfortunately, it Is long time since I hade issue working with both C# and VB, so I'm unaware of many thing these days Commented Jun 6, 2021 at 14:38
3

Strings.Asc is not equivalent with a plain C# cast for non ASCII chars that can go beyond 127 code value. The answer I found on 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 amounts to something like this:

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

Or, if you want the read deal add a reference to Microsoft.VisualBasic assembly.

2
  • This function works correctly for me. Casting, as this answer indicated, does not work correctly for non ASCII characters beyond 127. I do not recommend referencing the VisualBasic assembly in your C# project. If you are going to do that, then you might as well create a VB project.
    – Chris M.
    Commented Nov 26, 2018 at 22:13
  • Encoding.Default works differently between .NetStandard 2.0 and .NetFramework 4.x. At least when called from VB6 via COM Interop. Commented Jun 3, 2021 at 11:51
1

For Chr() you can use:

char chr = (char)you_char_value;
1

in C# you can use the Char.ConvertFromUtf32 statement

int intValue = 65;                                \\ Letter A    
string strVal = Char.ConvertFromUtf32(intValue);

the equivalent of VB's

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

No Microsoft.VisualBasic reference required

0

Add this method into 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;
            }
        }

`

1
  • Encoding.Default will not always work in netstandard 2.0 Commented Jun 3, 2021 at 11:45
0

I have extracted the Asc() function from Microsoft.VisualBasic.dll:

    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;
    }
1
  • Encoding.Default will not always work in netstandard 2.0 Commented Jun 3, 2021 at 11:45
0

//You can create the function and no need change your program

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

thanks to Soner Gönül

0

The following routine works for me in a COM Interop server environment of .net standard 2.0 + .net 5 and a Classic ASP/VB6 client, with a code page of 1252.

I have not tested it with other code pages:

   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);
    }
-1
 //Char to Int - ASC("]")
 int lIntAsc = (int)Char.Parse("]");
 Console.WriteLine(lIntAsc); //Return 91



 //Int to Char

char lChrChar = (char)91;
Console.WriteLine(lChrChar ); //Return "]"
2
  • 2
    Welcome to Stack Overflow! While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. Please also try not to crowd your code with explanatory comments, as this reduces the readability of both the code and the explanations!
    – Blue
    Commented Feb 23, 2018 at 14:21
  • Asc and Chr don't involve ASCII or even ISO 8859-1 (which is what your code does). They involve Encoding.Default. Commented Feb 23, 2018 at 15:07
-2

Given char c and int i, and functions fi(int) and fc(char):

From char to int (analog of VB Asc()): explicitly cast the char as an int: int i = (int)c;

or implicitly cast (promote): fi(char c) {i+= c;}

From int to char (analog of VB Chr()):

explicitly cast the int as an char: char c = (char)i, fc(int i) {(char)i};

An implicit cast is disallowed, as an int is wider (has a greater range of values) than a char

1
  • Simply casting is not an equivalent to the Stings,Asc function. You will not always return the correct value.
    – Chris M.
    Commented Nov 26, 2018 at 22:14

Not the answer you're looking for? Browse other questions tagged or ask your own question.