कैसे int.TryParse वास्तव में काम करता है


80

मैंने int.TryParseविधि कार्यान्वयन के लिए देखा है , यह वास्तव में कैसे काम करता है, लेकिन मुझे नहीं मिला है। मुझे पता है, एक के बारे में string, क्या यह एक संख्यात्मक मूल्य है, लेकिन मैं इस समय इसे परिवर्तित नहीं करना चाहता।

इसलिए मुझे केवल boolपरिणाम की आवश्यकता है int.TryParse। तो सवाल हैं:

  1. क्या कोई फ़ंक्शन है जो केवल boolपरिणाम प्रदान कर सकता है ,

तथा

  1. मैं जानना चाहता हूं, int.TryParseवास्तव में कैसे काम करता है (क्या try ... catchइनपुट के पात्रों के माध्यम से अंदर या पुनरावृत्त होता है string)?

1. नहीं, वहाँ नहीं है। आप उपयोग कर सकते हैं Convert.ToInt32(), लेकिन यह एक अपवाद फेंक देगा, अगर स्ट्रिंग को पार्स नहीं किया जा सकता है। 2. इसे स्ट्रिंग के माध्यम से पुनरावृत्त करना होगा, लेकिन यह संभवतः किसी भी अपवाद को नहीं पकड़ेगा, क्योंकि यह अपवाद को पकड़ने की तुलना में तेज़ हैConvert.ToInt32()
— Nolonar

आप regex ^ \ d + $ का उपयोग कर सकते हैं। या IsDigit के लिए प्रत्येक वर्ण का मूल्यांकन करें।
— पापराज्जो

जवाबों:


103

यदि आपको केवल boolपरिणाम की आवश्यकता है, तो केवल रिटर्न मान का उपयोग करें और outपैरामीटर को अनदेखा करें ।

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

संपादित करें : इस बीच आप मूल स्रोत कोड पर भी नज़र डाल सकते हैं :

System.Int32.TryParse


अगर मैं जानना चाहता हूं कि वास्तव में कुछ कैसे लागू किया जाता है, तो मैं ILSpy.NET-कोड को डिकंपाइल करने के लिए उपयोग कर रहा हूं ।

यह परिणाम है:

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

और नहीं, मैं Try-Catchsसड़क पर कोई नहीं देख सकता :

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

4
यह अधिक जटिल है तो मैं थकाऊ :) धन्यवाद!
— speti43

19

सिर्फ इसलिए int.TryParseकि आप मूल्य देता है इसका मतलब यह नहीं है कि आपको इसे रखने की आवश्यकता है; आप बहुत खुशी से ऐसा कर सकते हैं:

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

tempयदि आपको इसकी आवश्यकता नहीं है तो आप पूरी तरह से अनदेखा कर सकते हैं । यदि आपको इसकी आवश्यकता है, तो हे, यह आपके लिए इंतजार कर रहा है जब आप इसे चाहते हैं।

इंटर्नल के लिए, जहां तक ​​मुझे याद है कि यह एक इंट के रूप में स्ट्रिंग के कच्चे बाइट्स को पढ़ने का प्रयास करता है और परीक्षण करता है कि क्या परिणाम मान्य है, या कुछ और; यह गैर-संख्यात्मक वर्णों की तलाश के माध्यम से पुनरावृत्ति के रूप में सरल नहीं है।


16

हम अब C # 7.0 और इसके बाद के संस्करण को लिख सकते हैं:

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

यह सवाल का जवाब देने के लिए नहीं है।
— थीमफील्ड

1
क्या करता है?
— मृद २

@mrid यह निर्दिष्ट करता है कि कॉल स्कोप में एक वेरिएबल को राइट एक्सेस के साथ मेथ स्कोप को दिया जा रहा है। उदाहरण के लिए, यदि एक चर int someIntको int.TryParseपसंद किया जाता है int.TryParse(out someInt), तो int.TryParseवह अपना उत्पादन अंदर रख सकता है someInt, भले ही वह सामान्य रूप से दायरे से बाहर हो।
— तैमूर

@themefield - यह पोस्ट के शरीर में इस प्रश्न का सही उत्तर देता है: "तो प्रश्न ये हैं: 1) क्या कोई फ़ंक्शन है जो केवल बूल परिणाम प्रदान कर सकता है"।
— एंटीड्यूह

13

TryParse एकल पंक्ति में पार्स या मान्य के लिए सबसे अच्छा तरीका है:

int nNumber = int.TryParse("InputString", out nNumber) ? nNumber : 1;

संक्षिप्त वर्णन:

  1. nNumber शून्य से आरंभ करेगा,
  2. int.TryParse () "इनपुटस्ट्रीमिंग" को पार्स करने का प्रयास करें और इसे सफल करें, यदि nnumber में सेट किया गया है।
  3. कम अगर?: int.TryParse () परिणाम की जाँच करें, जो nNumber या 1 को डिफ़ॉल्ट मान के रूप में लौटाता है।

1
cannot use local variable 'nCurPage' before it is declared
— डेविन बर्क

प्रिय डेविन-बर्क, आप सही हैं, लेकिन यह काम करता है। बिना किसी त्रुटि या चेतावनी के मैं इसका कई बार उपयोग कर रहा हूं ...
— जोल्फघारी

8

Regex संकलित है इसलिए गति के लिए इसे एक बार बनाएं और पुन: उपयोग करें।
नई इस्मैच की तुलना में अधिक समय लेता है।
यह केवल सभी अंकों के लिए जाँच करता है।
यह रेंज के लिए जाँच नहीं करता है।
यदि आपको रेंज का परीक्षण करने की आवश्यकता है तो TryParse जाने का रास्ता है।

private static Regex regexInt = new Regex("^\\d+$");
static bool CheckReg(string value)
{
    return regexInt.IsMatch(value);
}

2

समझने के लिए इस सरल कार्यक्रम की जाँच करें int.TryParse

 class Program
 {
    static void Main()
    {
        string str = "7788";
        int num1;
        bool n = int.TryParse(str, out num1);
        Console.WriteLine(num1);
        Console.ReadLine();
    }
}

आउटपुट है: 7788

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.