TryParse is a piece of syntactic sugar that saves the developer from having to use a try/catch block to Parse an item. That's a great statement, but what does it actually mean?
Well, consider the following code sample:
int myInteger = int.MinValue;
string myValue = "A123";
try
{
myInteger = int.Parse(myValue);
}
catch (FormatException)
{
Console.WriteLine("Unable to parse myValue");
}
if (myInteger != int.MinValue)
{
}
As you are aware, using a catch is an expensive operation, so .NET 2 introduced the ability to TryParse. What this does is parse the value, and if the parse is successful, it puts the value into the out value. The reason that it returns bool is so that you know whether or not the parse was successful - this saves having to use a dummy value to test against (e.g using int.MinValue in the above sample).
OK, so we can accomplish the same as using the try/catch, but why would we choose to do it with TryParse? Well, the clue to this lies in the IL that's generated. If we rewrite the above code like this:
int myInteger;
string myValue = "A123";
bool test = int.TryParse(myValue, out myInteger);
Let's see what the IL looks like:
.entrypoint
.maxstack 2
.locals init (
[0] int32 myInteger,
[1] string myValue,
[2] bool test)
L_0000: nop
L_0001: ldstr "A123"
L_0006: stloc.1
L_0007: ldloc.1
L_0008: ldloca.s myInteger
L_000a: call bool [mscorlib]System.Int32::TryParse(string, int32&)
L_000f: stloc.2
L_0010: ret
The key line is L_000a. If we drill through this, we ultimately get to this:
.method private hidebysig static bool ParseNumber(char*& str, valuetype System.Globalization.NumberStyles options, valuetype System.Number/NumberBuffer& number, class System.Text.StringBuilder sb, class System.Globalization.NumberFormatInfo numfmt, bool parseDecimal) cil managed
{
.custom instance void System.Security.SecurityCriticalAttribute::.ctor()
.maxstack 4
.locals init (
[0] string str2,
[1] string str3,
[2] string str4,
[3] string str5,
[4] string str6,
[5] string str7,
[6] bool flag,
[7] int32 num,
[8] bool flag2,
[9] bool flag3,
[10] bool flag4,
[11] int32 num2,
[12] char* chPtr,
[13] char ch,
[14] char* chPtr2,
[15] int32 num3,
[16] int32 num4,
[17] bool flag5,
[18] char* chPtr3,
[19] int32 num5)
L_0000: ldarg.2
L_0001: ldc.i4.0
L_0002: stfld int32 System.Number/NumberBuffer::scale
L_0007: ldarg.2
L_0008: ldc.i4.0
L_0009: stfld bool System.Number/NumberBuffer::sign
L_000e: ldnull
L_000f: stloc.2
L_0010: ldnull
L_0011: stloc.3
L_0012: ldnull
L_0013: stloc.s str6
L_0015: ldnull
L_0016: stloc.s str7
L_0018: ldc.i4.0
L_0019: stloc.s flag
L_001b: ldarg.1
L_001c: ldc.i4 0x100
L_0021: and
L_0022: brfalse.s L_0064
L_0024: ldarg.s numfmt
L_0026: callvirt instance string System.Globalization.NumberFormatInfo::get_CurrencySymbol()
L_002b: stloc.2
L_002c: ldarg.s numfmt
L_002e: ldfld string System.Globalization.NumberFormatInfo::ansiCurrencySymbol
L_0033: brfalse.s L_003d
L_0035: ldarg.s numfmt
L_0037: ldfld string System.Globalization.NumberFormatInfo::ansiCurrencySymbol
L_003c: stloc.3
L_003d: ldarg.s numfmt
L_003f: callvirt instance string System.Globalization.NumberFormatInfo::get_NumberDecimalSeparator()
L_0044: stloc.s str6
L_0046: ldarg.s numfmt
L_0048: callvirt instance string System.Globalization.NumberFormatInfo::get_NumberGroupSeparator()
L_004d: stloc.s str7
L_004f: ldarg.s numfmt
L_0051: callvirt instance string System.Globalization.NumberFormatInfo::get_CurrencyDecimalSeparator()
L_0056: stloc.0
L_0057: ldarg.s numfmt
L_0059: callvirt instance string System.Globalization.NumberFormatInfo::get_CurrencyGroupSeparator()
L_005e: stloc.1
L_005f: ldc.i4.1
L_0060: stloc.s flag
L_0062: br.s L_0074
L_0064: ldarg.s numfmt
L_0066: callvirt instance string System.Globalization.NumberFormatInfo::get_NumberDecimalSeparator()
L_006b: stloc.0
L_006c: ldarg.s numfmt
L_006e: callvirt instance string System.Globalization.NumberFormatInfo::get_NumberGroupSeparator()
L_0073: stloc.1
L_0074: ldc.i4.0
L_0075: stloc.s num
L_0077: ldc.i4.0
L_0078: stloc.s flag2
L_007a: ldarg.3
L_007b: ldnull
L_007c: ceq
L_007e: ldc.i4.0
L_007f: ceq
L_0081: stloc.s flag3
L_0083: ldloc.s flag3
L_0085: brfalse.s L_0096
L_0087: ldarg.1
L_0088: ldc.i4 0x200
L_008d: and
L_008e: ldc.i4.0
L_008f: ceq
L_0091: ldc.i4.0
L_0092: ceq
L_0094: br.s L_0097
L_0096: ldc.i4.0
L_0097: stloc.s flag4
L_0099: ldloc.s flag3
L_009b: brtrue.s L_00a1
L_009d: ldc.i4.s 50
L_009f: br.s L_00a6
L_00a1: ldc.i4 0x7fffffff
L_00a6: stloc.s num2
L_00a8: ldarg.0
L_00a9: ldind.i
L_00aa: stloc.s chPtr
L_00ac: ldloc.s chPtr
L_00ae: ldind.u2
L_00af: stloc.s ch
L_00b1: ldloc.s ch
L_00b3: call bool System.Number::IsWhite(char)
L_00b8: brfalse.s L_00e5
L_00ba: ldarg.1
L_00bb: ldc.i4.1
L_00bc: and
L_00bd: brfalse.s L_00e5
L_00bf: ldloc.s num
L_00c1: ldc.i4.1
L_00c2: and
L_00c3: brfalse L_01a6
L_00c8: ldloc.s num
L_00ca: ldc.i4.1
L_00cb: and
L_00cc: brfalse.s L_00e5
L_00ce: ldloc.s num
L_00d0: ldc.i4.s 0x20
L_00d2: and
L_00d3: brtrue L_01a6
L_00d8: ldarg.s numfmt
L_00da: ldfld int32 System.Globalization.NumberFormatInfo::numberNegativePattern
L_00df: ldc.i4.2
L_00e0: beq L_01a6
L_00e5: ldarg.1
L_00e6: ldc.i4.4
L_00e7: and
L_00e8: brfalse.s L_00f3
L_00ea: ldloc.s num
L_00ec: ldc.i4.1
L_00ed: and
L_00ee: ldc.i4.0
L_00ef: ceq
L_00f1: br.s L_00f4
L_00f3: ldc.i4.0
L_00f4: dup
L_00f5: stloc.s flag2
L_00f7: brfalse.s L_0120
L_00f9: ldloc.s chPtr
L_00fb: ldarg.s numfmt
L_00fd: ldfld string System.Globalization.NumberFormatInfo::positiveSign
L_0102: call char* System.Number::MatchChars(char*, string)
L_0107: dup
L_0108: stloc.s chPtr2
L_010a: ldc.i4.0
L_010b: conv.u
L_010c: beq.s L_0120
L_010e: ldloc.s num
L_0110: ldc.i4.1
L_0111: or
L_0112: stloc.s num
L_0114: ldloc.s chPtr2
L_0116: ldc.i4.2
L_0117: conv.i
L_0118: sub
L_0119: stloc.s chPtr
L_011b: br L_01a6
L_0120: ldloc.s flag2
L_0122: brfalse.s L_014f
L_0124: ldloc.s chPtr
L_0126: ldarg.s numfmt
L_0128: ldfld string System.Globalization.NumberFormatInfo::negativeSign
L_012d: call char* System.Number::MatchChars(char*, string)
L_0132: dup
L_0133: stloc.s chPtr2
L_0135: ldc.i4.0
L_0136: conv.u
L_0137: beq.s L_014f
L_0139: ldloc.s num
L_013b: ldc.i4.1
L_013c: or
L_013d: stloc.s num
L_013f: ldarg.2
L_0140: ldc.i4.1
L_0141: stfld bool System.Number/NumberBuffer::sign
L_0146: ldloc.s chPtr2
L_0148: ldc.i4.2
L_0149: conv.i
L_014a: sub
L_014b: stloc.s chPtr
L_014d: br.s L_01a6
L_014f: ldloc.s ch
L_0151: ldc.i4.s 40
L_0153: bne.un.s L_0170
L_0155: ldarg.1
L_0156: ldc.i4.s 0x10
L_0158: and
L_0159: brfalse.s L_0170
L_015b: ldloc.s num
L_015d: ldc.i4.1
L_015e: and
L_015f: brtrue.s L_0170
L_0161: ldloc.s num
L_0163: ldc.i4.3
L_0164: or
L_0165: stloc.s num
L_0167: ldarg.2
L_0168: ldc.i4.1
L_0169: stfld bool System.Number/NumberBuffer::sign
L_016e: br.s L_01a6
L_0170: ldloc.2
L_0171: brfalse.s L_0182
L_0173: ldloc.s chPtr
L_0175: ldloc.2
L_0176: call char* System.Number::MatchChars(char*, string)
L_017b: dup
L_017c: stloc.s chPtr2
L_017e: ldc.i4.0
L_017f: conv.u
L_0180: bne.un.s L_0194
L_0182: ldloc.3
L_0183: brfalse.s L_01b6
L_0185: ldloc.s chPtr
L_0187: ldloc.3
L_0188: call char* System.Number::MatchChars(char*, string)
L_018d: dup
L_018e: stloc.s chPtr2
L_0190: ldc.i4.0
L_0191: conv.u
L_0192: beq.s L_01b6
L_0194: ldloc.s num
L_0196: ldc.i4.s 0x20
L_0198: or
L_0199: stloc.s num
L_019b: ldnull
L_019c: stloc.2
L_019d: ldnull
L_019e: stloc.3
L_019f: ldloc.s chPtr2
L_01a1: ldc.i4.2
L_01a2: conv.i
L_01a3: sub
L_01a4: stloc.s chPtr
L_01a6: ldloc.s chPtr
L_01a8: ldc.i4.2
L_01a9: conv.i
L_01aa: add
L_01ab: dup
L_01ac: stloc.s chPtr
L_01ae: ldind.u2
L_01af: stloc.s ch
L_01b1: br L_00b1
L_01b6: ldc.i4.0
L_01b7: stloc.s num3
L_01b9: ldc.i4.0
L_01ba: stloc.s num4
L_01bc: ldloc.s ch
L_01be: ldc.i4.s 0x30
L_01c0: blt.s L_01c8
L_01c2: ldloc.s ch
L_01c4: ldc.i4.s 0x39
L_01c6: ble.s L_01f2
L_01c8: ldarg.1
L_01c9: ldc.i4 0x200
L_01ce: and
L_01cf: brfalse L_027c
L_01d4: ldloc.s ch
L_01d6: ldc.i4.s 0x61
L_01d8: blt.s L_01e0
L_01da: ldloc.s ch
L_01dc: ldc.i4.s 0x66
L_01de: ble.s L_01f2
L_01e0: ldloc.s ch
L_01e2: ldc.i4.s 0x41
L_01e4: blt L_027c
L_01e9: ldloc.s ch
L_01eb: ldc.i4.s 70
L_01ed: bgt L_027c
L_01f2: ldloc.s num
L_01f4: ldc.i4.4
L_01f5: or
L_01f6: stloc.s num
L_01f8: ldloc.s ch
L_01fa: ldc.i4.s 0x30
L_01fc: bne.un.s L_0208
L_01fe: ldloc.s num
L_0200: ldc.i4.8
L_0201: and
L_0202: brtrue.s L_0208
L_0204: ldloc.s flag4
L_0206: brfalse.s L_025f
L_0208: ldloc.s num3
L_020a: ldloc.s num2
L_020c: bge.s L_023f
L_020e: ldloc.s flag3
L_0210: brfalse.s L_021d
L_0212: ldarg.3
L_0213: ldloc.s ch
L_0215: callvirt instance class System.Text.StringBuilder System.Text.StringBuilder::Append(char)
L_021a: pop
L_021b: br.s L_0231
L_021d: ldarg.2
L_021e: ldfld char* System.Number/NumberBuffer::digits
L_0223: ldloc.s num3
L_0225: dup
L_0226: ldc.i4.1
L_0227: add
L_0228: stloc.s num3
L_022a: conv.i
L_022b: ldc.i4.2
L_022c: mul
L_022d: add
L_022e: ldloc.s ch
L_0230: stind.i2
L_0231: ldloc.s ch
L_0233: ldc.i4.s 0x30
L_0235: bne.un.s L_023b
L_0237: ldarg.s parseDecimal
L_0239: brfalse.s L_023f
L_023b: ldloc.s num3
L_023d: stloc.s num4
L_023f: ldloc.s num
L_0241: ldc.i4.s 0x10
L_0243: and
L_0244: brtrue.s L_0254
L_0246: ldarg.2
L_0247: dup
L_0248: ldfld int32 System.Number/NumberBuffer::scale
L_024d: ldc.i4.1
L_024e: add
L_024f: stfld int32 System.Number/NumberBuffer::scale
L_0254: ldloc.s num
L_0256: ldc.i4.8
L_0257: or
L_0258: stloc.s num
L_025a: br L_0307
L_025f: ldloc.s num
L_0261: ldc.i4.s 0x10
L_0263: and
L_0264: brfalse L_0307
L_0269: ldarg.2
L_026a: dup
L_026b: ldfld int32 System.Number/NumberBuffer::scale
L_0270: ldc.i4.1
L_0271: sub
L_0272: stfld int32 System.Number/NumberBuffer::scale
L_0277: br L_0307
L_027c: ldarg.1
L_027d: ldc.i4.s 0x20
L_027f: and
L_0280: brfalse.s L_02c3
L_0282: ldloc.s num
L_0284: ldc.i4.s 0x10
L_0286: and
L_0287: brtrue.s L_02c3
L_0289: ldloc.s chPtr
L_028b: ldloc.0
L_028c: call char* System.Number::MatchChars(char*, string)
L_0291: dup
L_0292: stloc.s chPtr2
L_0294: ldc.i4.0
L_0295: conv.u
L_0296: bne.un.s L_02b3
L_0298: ldloc.s flag
L_029a: brfalse.s L_02c3
L_029c: ldloc.s num
L_029e: ldc.i4.s 0x20
L_02a0: and
L_02a1: brtrue.s L_02c3
L_02a3: ldloc.s chPtr
L_02a5: ldloc.s str6
L_02a7: call char* System.Number::MatchChars(char*, string)
L_02ac: dup
L_02ad: stloc.s chPtr2
L_02af: ldc.i4.0
L_02b0: conv.u
L_02b1: beq.s L_02c3
L_02b3: ldloc.s num
L_02b5: ldc.i4.s 0x10
L_02b7: or
L_02b8: stloc.s num
L_02ba: ldloc.s chPtr2
L_02bc: ldc.i4.2
L_02bd: conv.i
L_02be: sub
L_02bf: stloc.s chPtr
L_02c1: br.s L_0307
L_02c3: ldarg.1
L_02c4: ldc.i4.s 0x40
L_02c6: and
L_02c7: brfalse.s L_0317
L_02c9: ldloc.s num
L_02cb: ldc.i4.4
L_02cc: and
L_02cd: brfalse.s L_0317
L_02cf: ldloc.s num
L_02d1: ldc.i4.s 0x10
L_02d3: and
L_02d4: brtrue.s L_0317
L_02d6: ldloc.s chPtr
L_02d8: ldloc.1
L_02d9: call char* System.Number::MatchChars(char*, string)
L_02de: dup
L_02df: stloc.s chPtr2
L_02e1: ldc.i4.0
L_02e2: conv.u
L_02e3: bne.un.s L_0300
L_02e5: ldloc.s flag
L_02e7: brfalse.s L_0317
L_02e9: ldloc.s num
L_02eb: ldc.i4.s 0x20
L_02ed: and
L_02ee: brtrue.s L_0317
L_02f0: ldloc.s chPtr
L_02f2: ldloc.s str7
L_02f4: call char* System.Number::MatchChars(char*, string)
L_02f9: dup
L_02fa: stloc.s chPtr2
L_02fc: ldc.i4.0
L_02fd: conv.u
L_02fe: beq.s L_0317
L_0300: ldloc.s chPtr2
L_0302: ldc.i4.2
L_0303: conv.i
L_0304: sub
L_0305: stloc.s chPtr
L_0307: ldloc.s chPtr
L_0309: ldc.i4.2
L_030a: conv.i
L_030b: add
L_030c: dup
L_030d: stloc.s chPtr
L_030f: ldind.u2
L_0310: stloc.s ch
L_0312: br L_01bc
L_0317: ldc.i4.0
L_0318: stloc.s flag5
L_031a: ldarg.2
L_031b: ldloc.s num4
L_031d: stfld int32 System.Number/NumberBuffer::precision
L_0322: ldloc.s flag3
L_0324: brfalse.s L_0330
L_0326: ldarg.3
L_0327: ldc.i4.0
L_0328: callvirt instance class System.Text.StringBuilder System.Text.StringBuilder::Append(char)
L_032d: pop
L_032e: br.s L_033e
L_0330: ldarg.2
L_0331: ldfld char* System.Number/NumberBuffer::digits
L_0336: ldloc.s num4
L_0338: conv.i
L_0339: ldc.i4.2
L_033a: mul
L_033b: add
L_033c: ldc.i4.0
L_033d: stind.i2
L_033e: ldloc.s num
L_0340: ldc.i4.4
L_0341: and
L_0342: brfalse L_0526
L_0347: ldloc.s ch
L_0349: ldc.i4.s 0x45
L_034b: beq.s L_0356
L_034d: ldloc.s ch
L_034f: ldc.i4.s 0x65
L_0351: bne.un L_042f
L_0356: ldarg.1
L_0357: ldc.i4 0x80
L_035c: and
L_035d: brfalse L_042f
L_0362: ldloc.s chPtr
L_0364: stloc.s chPtr3
L_0366: ldloc.s chPtr
L_0368: ldc.i4.2
L_0369: conv.i
L_036a: add
L_036b: dup
L_036c: stloc.s chPtr
L_036e: ldind.u2
L_036f: stloc.s ch
L_0371: ldloc.s chPtr
L_0373: ldarg.s numfmt
L_0375: ldfld string System.Globalization.NumberFormatInfo::positiveSign
L_037a: call char* System.Number::MatchChars(char*, string)
L_037f: dup
L_0380: stloc.s chPtr2
L_0382: ldc.i4.0
L_0383: conv.u
L_0384: beq.s L_0390
L_0386: ldloc.s chPtr2
L_0388: dup
L_0389: stloc.s chPtr
L_038b: ldind.u2
L_038c: stloc.s ch
L_038e: br.s L_03b0
L_0390: ldloc.s chPtr
L_0392: ldarg.s numfmt
L_0394: ldfld string System.Globalization.NumberFormatInfo::negativeSign
L_0399: call char* System.Number::MatchChars(char*, string)
L_039e: dup
L_039f: stloc.s chPtr2
L_03a1: ldc.i4.0
L_03a2: conv.u
L_03a3: beq.s L_03b0
L_03a5: ldloc.s chPtr2
L_03a7: dup
L_03a8: stloc.s chPtr
L_03aa: ldind.u2
L_03ab: stloc.s ch
L_03ad: ldc.i4.1
L_03ae: stloc.s flag5
L_03b0: ldloc.s ch
L_03b2: ldc.i4.s 0x30
L_03b4: blt.s L_0426
L_03b6: ldloc.s ch
L_03b8: ldc.i4.s 0x39
L_03ba: bgt.s L_0426
L_03bc: ldc.i4.0
L_03bd: stloc.s num5
L_03bf: ldloc.s num5
L_03c1: ldc.i4.s 10
L_03c3: mul
L_03c4: ldloc.s ch
L_03c6: ldc.i4.s 0x30
L_03c8: sub
L_03c9: add
L_03ca: stloc.s num5
L_03cc: ldloc.s chPtr
L_03ce: ldc.i4.2
L_03cf: conv.i
L_03d0: add
L_03d1: dup
L_03d2: stloc.s chPtr
L_03d4: ldind.u2
L_03d5: stloc.s ch
L_03d7: ldloc.s num5
L_03d9: ldc.i4 0x3e8
L_03de: ble.s L_0400
L_03e0: ldc.i4 0x270f
L_03e5: stloc.s num5
L_03e7: br.s L_03f4
L_03e9: ldloc.s chPtr
L_03eb: ldc.i4.2
L_03ec: conv.i
L_03ed: add
L_03ee: dup
L_03ef: stloc.s chPtr
L_03f1: ldind.u2
L_03f2: stloc.s ch
L_03f4: ldloc.s ch
L_03f6: ldc.i4.s 0x30
L_03f8: blt.s L_0400
L_03fa: ldloc.s ch
L_03fc: ldc.i4.s 0x39
L_03fe: ble.s L_03e9
L_0400: ldloc.s ch
L_0402: ldc.i4.s 0x30
L_0404: blt.s L_040c
L_0406: ldloc.s ch
L_0408: ldc.i4.s 0x39
L_040a: ble.s L_03bf
L_040c: ldloc.s flag5
L_040e: brfalse.s L_0415
L_0410: ldloc.s num5
L_0412: neg
L_0413: stloc.s num5
L_0415: ldarg.2
L_0416: dup
L_0417: ldfld int32 System.Number/NumberBuffer::scale
L_041c: ldloc.s num5
L_041e: add
L_041f: stfld int32 System.Number/NumberBuffer::scale
L_0424: br.s L_042f
L_0426: ldloc.s chPtr3
L_0428: stloc.s chPtr
L_042a: ldloc.s chPtr
L_042c: ldind.u2
L_042d: stloc.s ch
L_042f: ldloc.s ch
L_0431: call bool System.Number::IsWhite(char)
L_0436: brfalse.s L_0440
L_0438: ldarg.1
L_0439: ldc.i4.2
L_043a: and
L_043b: brtrue L_04eb
L_0440: ldarg.1
L_0441: ldc.i4.8
L_0442: and
L_0443: brfalse.s L_044e
L_0445: ldloc.s num
L_0447: ldc.i4.1
L_0448: and
L_0449: ldc.i4.0
L_044a: ceq
L_044c: br.s L_044f
L_044e: ldc.i4.0
L_044f: dup
L_0450: stloc.s flag2
L_0452: brfalse.s L_0478
L_0454: ldloc.s chPtr
L_0456: ldarg.s numfmt
L_0458: ldfld string System.Globalization.NumberFormatInfo::positiveSign
L_045d: call char* System.Number::MatchChars(char*, string)
L_0462: dup
L_0463: stloc.s chPtr2
L_0465: ldc.i4.0
L_0466: conv.u
L_0467: beq.s L_0478
L_0469: ldloc.s num
L_046b: ldc.i4.1
L_046c: or
L_046d: stloc.s num
L_046f: ldloc.s chPtr2
L_0471: ldc.i4.2
L_0472: conv.i
L_0473: sub
L_0474: stloc.s chPtr
L_0476: br.s L_04eb
L_0478: ldloc.s flag2
L_047a: brfalse.s L_04a7
L_047c: ldloc.s chPtr
L_047e: ldarg.s numfmt
L_0480: ldfld string System.Globalization.NumberFormatInfo::negativeSign
L_0485: call char* System.Number::MatchChars(char*, string)
L_048a: dup
L_048b: stloc.s chPtr2
L_048d: ldc.i4.0
L_048e: conv.u
L_048f: beq.s L_04a7
L_0491: ldloc.s num
L_0493: ldc.i4.1
L_0494: or
L_0495: stloc.s num
L_0497: ldarg.2
L_0498: ldc.i4.1
L_0499: stfld bool System.Number/NumberBuffer::sign
L_049e: ldloc.s chPtr2
L_04a0: ldc.i4.2
L_04a1: conv.i
L_04a2: sub
L_04a3: stloc.s chPtr
L_04a5: br.s L_04eb
L_04a7: ldloc.s ch
L_04a9: ldc.i4.s 0x29
L_04ab: bne.un.s L_04bc
L_04ad: ldloc.s num
L_04af: ldc.i4.2
L_04b0: and
L_04b1: brfalse.s L_04bc
L_04b3: ldloc.s num
L_04b5: ldc.i4.s -3
L_04b7: and
L_04b8: stloc.s num
L_04ba: br.s L_04eb
L_04bc: ldloc.2
L_04bd: brfalse.s L_04ce
L_04bf: ldloc.s chPtr
L_04c1: ldloc.2
L_04c2: call char* System.Number::MatchChars(char*, string)
L_04c7: dup
L_04c8: stloc.s chPtr2
L_04ca: ldc.i4.0
L_04cb: conv.u
L_04cc: bne.un.s L_04e0
L_04ce: ldloc.3
L_04cf: brfalse.s L_04fb
L_04d1: ldloc.s chPtr
L_04d3: ldloc.3
L_04d4: call char* System.Number::MatchChars(char*, string)
L_04d9: dup
L_04da: stloc.s chPtr2
L_04dc: ldc.i4.0
L_04dd: conv.u
L_04de: beq.s L_04fb
L_04e0: ldnull
L_04e1: stloc.2
L_04e2: ldnull
L_04e3: stloc.3
L_04e4: ldloc.s chPtr2
L_04e6: ldc.i4.2
L_04e7: conv.i
L_04e8: sub
L_04e9: stloc.s chPtr
L_04eb: ldloc.s chPtr
L_04ed: ldc.i4.2
L_04ee: conv.i
L_04ef: add
L_04f0: dup
L_04f1: stloc.s chPtr
L_04f3: ldind.u2
L_04f4: stloc.s ch
L_04f6: br L_042f
L_04fb: ldloc.s num
L_04fd: ldc.i4.2
L_04fe: and
L_04ff: brtrue.s L_0526
L_0501: ldloc.s num
L_0503: ldc.i4.8
L_0504: and
L_0505: brtrue.s L_0520
L_0507: ldarg.s parseDecimal
L_0509: brtrue.s L_0512
L_050b: ldarg.2
L_050c: ldc.i4.0
L_050d: stfld int32 System.Number/NumberBuffer::scale
L_0512: ldloc.s num
L_0514: ldc.i4.s 0x10
L_0516: and
L_0517: brtrue.s L_0520
L_0519: ldarg.2
L_051a: ldc.i4.0
L_051b: stfld bool System.Number/NumberBuffer::sign
L_0520: ldarg.0
L_0521: ldloc.s chPtr
L_0523: stind.i
L_0524: ldc.i4.1
L_0525: ret
L_0526: ldarg.0
L_0527: ldloc.s chPtr
L_0529: stind.i
L_052a: ldc.i4.0
L_052b: ret
}
This code is the piece that actually parses the number. The key thing here, though, is that the chain of code that gets to this does not use exception handling anywhere. This means that we aren't using an expensive way to handle invalid cases.