TechAurelian
TechAurelian

Reputation: 5811

Convert a string containing a hexadecimal value starting with "0x" to an integer or long

How can I convert a string value like "0x310530" to an integer value in C#?

I've tried int.TryParse (and even int.TryParse with System.Globalization.NumberStyles.Any) but it does not work.

UPDATE: It seems that Convert.ToInt64 or Convert.ToInt32 work without having to remove the leading "0x":

long hwnd = Convert.ToInt64("0x310530", 16);

The documentation of Convert.ToInt64 Method (String, Int32) says:

"If fromBase is 16, you can prefix the number specified by the value parameter with "0x" or "0X"."

However, I would prefer a method like TryParse that does not raise exceptions.

Upvotes: 32

Views: 53030

Answers (6)

Uber Kluger
Uber Kluger

Reputation: 502

All the answers prior to today are valid responses to the wording of the question but I suspect that they might have missed the underlying intent. If the OP simply had one or more strings beginning "0x" then just skipping the first 2 characters would easily solve the problem with both int.Parse and int.TryParse (as already suggested by others). For mixed strings of hex digits where not all have an "0x" prefix, use of String.StartsWith(string) could be used to identify those that need trimming. It would seem likely that most C# users would know about String.Substring(Int32) as in the example by dtb. Using Convert.ToInt32(string? value, Int32 frombase) does allow the "0x" to remain in place but only if frombase is 16 meaning that, again, it is just skipping the "0x". I suspect that even if it was not the intent of the OP, most readers are here because (like me) they want to be able to automatically convert a string beginning "0x"/"0X" as hexadecimal but otherwise convert as decimal (as with strtol from C and C++ or parseInt from ECMAScript or, indeed, the C# language parser itself). Unfortunately, despite much searching, I think the simple answer is that you can't or, more precisely, there are no predefined classes that provide this functionality, you will have to do it yourself. Not that it is especially difficult...

// Ignoring checks that s is not null but if this were a member function
// of a class in a library then all relevant checks should be included.

string  s = "0x1310530";
int     value;

// using Parse needs exception handling

if (s.Length > 1 && s.Substring(0, 2).ToLowerInvariant() == "0x")
    value = int.Parse(s.Substring(2), NumberStyles.AllowHexSpecifier);
else
    value = int.Parse(s);

// using TryParse avoids exceptions (unless the NumberStyles argument is invalid)

bool    parseok;

if (s.Length > 1 && s.Substring(0, 2).ToLowerInvariant() == "0x")
    parseok = int.TryParse(s.Substring(2), NumberStyles.AllowHexSpecifier, null, out value);
else
    parseok = int.TryParse(s, out value);

// using Convert.ToInt32 for just hex or decimal (note: exceptions)

int     frombase = 10;

if (s.Length > 1 && s.Substring(0, 2).ToLowerInvariant() == "0x")
    frombase = 16;
value = Convert.ToInt32(s, frombase); // don't need to remove the 0x

// using Convert.ToInt32 allows the possibility of octal and binary as well

bool     skipprefix = false;

if (s.Length > 1 && s[0] == '0')
// single digits or no leading 0 means convert as decimal string
// "" will generate ArgumentOutOfRangeException as expected
        switch(s[1]) // can't be just "0", already checked that
        {
        case 'x':
        case 'X':
                frombase = 16;
                break;

        case 'b':
        case 'B':
                frombase = 2;
                skipprefix = true;
                break;

        default:
                frombase = 8;
                break;
        }
value = Convert.ToInt32(skipprefix ? s.Substring(2) : s, frombase);
// still don't need to remove leading "0x" or "0" but "0b" must go

Comments declaring me wrong and listing the class(es) which can do this (and which are readily available in older versions of .NET for those working on non-updatable systems) are very welcome.

Upvotes: 1

Peter
Peter

Reputation: 14508

Building further upon Caverna's answer I added a tryparse method so we can test if a conversion is valid to a certain type.

public static T GetTfromString<T>(string mystring)
{
    var foo = TypeDescriptor.GetConverter(typeof(T));
    return (T)(foo.ConvertFromInvariantString(mystring));
}

public static bool TryGetTFromString<T>(string mystring, out T value)
{
    try
    {
        value = GetTfromString<T>(mystring);
        return true;
    }
    catch (FormatException)
    {
        value = default(T);
        return false;
    }
}

Upvotes: 0

Caverna
Caverna

Reputation: 450

Direct from SHanselman, as pointed by Cristi Diaconescu, but I've included the main source code:

public static T GetTfromString<T>(string mystring)
{
   var foo = TypeDescriptor.GetConverter(typeof(T));
   return (T)(foo.ConvertFromInvariantString(mystring));
}

The whole article deserves a closer look!

Upvotes: 3

Hans Passant
Hans Passant

Reputation: 941327

int value = (int)new System.ComponentModel.Int32Converter().ConvertFromString("0x310530");

Upvotes: 31

dtb
dtb

Reputation: 217263

From MSDN:

NumberStyles.AllowHexSpecifier

Indicates that the numeric string represents a hexadecimal value. Valid hexadecimal values include the numeric digits 0-9 and the hexadecimal digits A-F and a-f. Strings that are parsed using this style cannot be prefixed with "0x" or "&h".

So you have to strip out the 0x prefix first:

string s = "0x310530";
int result;

if (s != null && s.StartsWith("0x") && int.TryParse(s.Substring(2),
                                                    NumberStyles.AllowHexSpecifier,
                                                    null,
                                                    out result))
{
    // result == 3212592
}

Upvotes: 18

Orjanp
Orjanp

Reputation: 10921

If you remove the leading 0x, you could use int.Parse

int a = int.Parse("1310530", NumberStyles.AllowHexSpecifier);

Upvotes: 1

Related Questions