Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How the int.TryParse actually works

Tags:

c#

I've looked for int.TryParse method implementation, how does it work actually, but I haven't found. I have to know, about a string, whether it's a numeric value, but I don't want to convert it at the this time.

So I need only the bool result from int.TryParse. So the questions are:

  1. Is there any function which can provide only the bool result,

and

  1. I'd like to know, how the int.TryParse actually works (is there a try ... catch inside or iterates through the characters of input string)?
like image 912
speti43 Avatar asked Mar 08 '13 13:03

speti43


People also ask

How does TryParse int work?

TryParse(String, NumberStyles, IFormatProvider, Int32) Converts the string representation of a number in a specified style and culture-specific format to its 32-bit signed integer equivalent. A return value indicates whether the conversion succeeded.

What does int TryParse return?

The Int32. TryParse() method returns a boolean value as return and provides the converted value as an out parameter.

What does TryParse return if successful?

TryParse method converts a string value to a corresponding 32-bit signed integer value data type. It returns a Boolean value True , if conversion successful and False , if conversion failed.

Why should one use TryParse instead of parse?

Parse() method throws an exception if it cannot parse the value, whereas TryParse() method returns a bool indicating whether it succeeded. However, TryParse does not return the value, it returns a status code to indicate whether the parse succeeded and does not throw exception.


2 Answers

If you only need the bool result, just use the return value and ignore the out parameter.

bool successfullyParsed = int.TryParse(str, out ignoreMe); if (successfullyParsed){     // ... } 

Edit: Meanwhile you can also have a look at the original source code:

System.Int32.TryParse


If i want to know how something is actually implemented, i'm using ILSpy to decompile the .NET-code.

This is the result:

// int /// <summary>Converts the string representation of a number to its 32-bit signed integer equivalent. A return value indicates whether the operation succeeded.</summary> /// <returns>true if s was converted successfully; otherwise, false.</returns> /// <param name="s">A string containing a number to convert. </param> /// <param name="result">When this method returns, contains the 32-bit signed integer value equivalent to the number contained in s, if the conversion succeeded, or zero if the conversion failed. The conversion fails if the s parameter is null, is not of the correct format, or represents a number less than <see cref="F:System.Int32.MinValue"></see> or greater than <see cref="F:System.Int32.MaxValue"></see>. This parameter is passed uninitialized. </param> /// <filterpriority>1</filterpriority> public static bool TryParse(string s, out int result) {     return Number.TryParseInt32(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result); }   // System.Number internal unsafe static bool TryParseInt32(string s, NumberStyles style, NumberFormatInfo info, out int result) {     byte* stackBuffer = stackalloc byte[1 * 114 / 1];     Number.NumberBuffer numberBuffer = new Number.NumberBuffer(stackBuffer);     result = 0;     if (!Number.TryStringToNumber(s, style, ref numberBuffer, info, false))     {         return false;     }     if ((style & NumberStyles.AllowHexSpecifier) != NumberStyles.None)     {         if (!Number.HexNumberToInt32(ref numberBuffer, ref result))         {             return false;         }     }     else     {         if (!Number.NumberToInt32(ref numberBuffer, ref result))         {             return false;         }     }     return true; } 

And no, i cannot see any Try-Catchs on the road:

// System.Number private unsafe static bool TryStringToNumber(string str, NumberStyles options, ref Number.NumberBuffer number, NumberFormatInfo numfmt, bool parseDecimal) {     if (str == null)     {         return false;     }     fixed (char* ptr = str)     {         char* ptr2 = ptr;         if (!Number.ParseNumber(ref ptr2, options, ref number, numfmt, parseDecimal) || ((ptr2 - ptr / 2) / 2 < str.Length && !Number.TrailingZeros(str, (ptr2 - ptr / 2) / 2)))         {             return false;         }     }     return true; }  // System.Number private unsafe static bool ParseNumber(ref char* str, NumberStyles options, ref Number.NumberBuffer number, NumberFormatInfo numfmt, bool parseDecimal) {     number.scale = 0;     number.sign = false;     string text = null;     string text2 = null;     string str2 = null;     string str3 = null;     bool flag = false;     string str4;     string str5;     if ((options & NumberStyles.AllowCurrencySymbol) != NumberStyles.None)     {         text = numfmt.CurrencySymbol;         if (numfmt.ansiCurrencySymbol != null)         {             text2 = numfmt.ansiCurrencySymbol;         }         str2 = numfmt.NumberDecimalSeparator;         str3 = numfmt.NumberGroupSeparator;         str4 = numfmt.CurrencyDecimalSeparator;         str5 = numfmt.CurrencyGroupSeparator;         flag = true;     }     else     {         str4 = numfmt.NumberDecimalSeparator;         str5 = numfmt.NumberGroupSeparator;     }     int num = 0;     char* ptr = str;     char c = *ptr;     while (true)     {         if (!Number.IsWhite(c) || (options & NumberStyles.AllowLeadingWhite) == NumberStyles.None || ((num & 1) != 0 && ((num & 1) == 0 || ((num & 32) == 0 && numfmt.numberNegativePattern != 2))))         {             bool flag2;             char* ptr2;             if ((flag2 = ((options & NumberStyles.AllowLeadingSign) != NumberStyles.None && (num & 1) == 0)) && (ptr2 = Number.MatchChars(ptr, numfmt.positiveSign)) != null)             {                 num |= 1;                 ptr = ptr2 - (IntPtr)2 / 2;             }             else             {                 if (flag2 && (ptr2 = Number.MatchChars(ptr, numfmt.negativeSign)) != null)                 {                     num |= 1;                     number.sign = true;                     ptr = ptr2 - (IntPtr)2 / 2;                 }                 else                 {                     if (c == '(' && (options & NumberStyles.AllowParentheses) != NumberStyles.None && (num & 1) == 0)                     {                         num |= 3;                         number.sign = true;                     }                     else                     {                         if ((text == null || (ptr2 = Number.MatchChars(ptr, text)) == null) && (text2 == null || (ptr2 = Number.MatchChars(ptr, text2)) == null))                         {                             break;                         }                         num |= 32;                         text = null;                         text2 = null;                         ptr = ptr2 - (IntPtr)2 / 2;                     }                 }             }         }         c = *(ptr += (IntPtr)2 / 2);     }     int num2 = 0;     int num3 = 0;     while (true)     {         if ((c >= '0' && c <= '9') || ((options & NumberStyles.AllowHexSpecifier) != NumberStyles.None && ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))))         {             num |= 4;             if (c != '0' || (num & 8) != 0)             {                 if (num2 < 50)                 {                     number.digits[(IntPtr)(num2++)] = c;                     if (c != '0' || parseDecimal)                     {                         num3 = num2;                     }                 }                 if ((num & 16) == 0)                 {                     number.scale++;                 }                 num |= 8;             }             else             {                 if ((num & 16) != 0)                 {                     number.scale--;                 }             }         }         else         {             char* ptr2;             if ((options & NumberStyles.AllowDecimalPoint) != NumberStyles.None && (num & 16) == 0 && ((ptr2 = Number.MatchChars(ptr, str4)) != null || (flag && (num & 32) == 0 && (ptr2 = Number.MatchChars(ptr, str2)) != null)))             {                 num |= 16;                 ptr = ptr2 - (IntPtr)2 / 2;             }             else             {                 if ((options & NumberStyles.AllowThousands) == NumberStyles.None || (num & 4) == 0 || (num & 16) != 0 || ((ptr2 = Number.MatchChars(ptr, str5)) == null && (!flag || (num & 32) != 0 || (ptr2 = Number.MatchChars(ptr, str3)) == null)))                 {                     break;                 }                 ptr = ptr2 - (IntPtr)2 / 2;             }         }         c = *(ptr += (IntPtr)2 / 2);     }     bool flag3 = false;     number.precision = num3;     number.digits[(IntPtr)num3] = '\0';     if ((num & 4) != 0)     {         if ((c == 'E' || c == 'e') && (options & NumberStyles.AllowExponent) != NumberStyles.None)         {             char* ptr3 = ptr;             c = *(ptr += (IntPtr)2 / 2);             char* ptr2;             if ((ptr2 = Number.MatchChars(ptr, numfmt.positiveSign)) != null)             {                 c = *(ptr = ptr2);             }             else             {                 if ((ptr2 = Number.MatchChars(ptr, numfmt.negativeSign)) != null)                 {                     c = *(ptr = ptr2);                     flag3 = true;                 }             }             if (c >= '0' && c <= '9')             {                 int num4 = 0;                 do                 {                     num4 = num4 * 10 + (int)(c - '0');                     c = *(ptr += (IntPtr)2 / 2);                     if (num4 > 1000)                     {                         num4 = 9999;                         while (c >= '0' && c <= '9')                         {                             c = *(ptr += (IntPtr)2 / 2);                         }                     }                 }                 while (c >= '0' && c <= '9');                 if (flag3)                 {                     num4 = -num4;                 }                 number.scale += num4;             }             else             {                 ptr = ptr3;                 c = *ptr;             }         }         while (true)         {             if (!Number.IsWhite(c) || (options & NumberStyles.AllowTrailingWhite) == NumberStyles.None)             {                 bool flag2;                 char* ptr2;                 if ((flag2 = ((options & NumberStyles.AllowTrailingSign) != NumberStyles.None && (num & 1) == 0)) && (ptr2 = Number.MatchChars(ptr, numfmt.positiveSign)) != null)                 {                     num |= 1;                     ptr = ptr2 - (IntPtr)2 / 2;                 }                 else                 {                     if (flag2 && (ptr2 = Number.MatchChars(ptr, numfmt.negativeSign)) != null)                     {                         num |= 1;                         number.sign = true;                         ptr = ptr2 - (IntPtr)2 / 2;                     }                     else                     {                         if (c == ')' && (num & 2) != 0)                         {                             num &= -3;                         }                         else                         {                             if ((text == null || (ptr2 = Number.MatchChars(ptr, text)) == null) && (text2 == null || (ptr2 = Number.MatchChars(ptr, text2)) == null))                             {                                 break;                             }                             text = null;                             text2 = null;                             ptr = ptr2 - (IntPtr)2 / 2;                         }                     }                 }             }             c = *(ptr += (IntPtr)2 / 2);         }         if ((num & 2) == 0)         {             if ((num & 8) == 0)             {                 if (!parseDecimal)                 {                     number.scale = 0;                 }                 if ((num & 16) == 0)                 {                     number.sign = false;                 }             }             str = ptr;             return true;         }     }     str = ptr;     return false; } 
like image 166
Tim Schmelter Avatar answered Sep 21 '22 12:09

Tim Schmelter


Just because int.TryParse gives you the value doesn't mean you need to keep it; you can quite happily do this:

int temp; if (int.TryParse(inputString, out temp)) {     // do stuff } 

You can ignore temp entirely if you don't need it. If you do need it, then hey, it's waiting for you when you want it.

As for the internals, as far as I remember it attempts to read the raw bytes of the string as an int and tests whether the result is valid, or something; it's not as simple as iterating through looking for non-numeric characters.

like image 44
anaximander Avatar answered Sep 24 '22 12:09

anaximander