@@ -412,19 +412,34 @@ internal static unsafe void DecimalToNumber(scoped ref decimal d, ref NumberBuff
412412 number . CheckConsistency ( ) ;
413413 }
414414
415+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
415416 private static int GetFloatingPointMaxDigitsAndPrecision ( char fmt , ref int precision , NumberFormatInfo info , out bool isSignificantDigits )
416417 {
417- if ( fmt == 0 )
418+ // We want to fast path the common case of no format and general format + precision.
419+ // These are commonly encountered and the full switch is otherwise large enough to show up in hot path profiles
420+
421+ fmt |= 0x20 ;
422+
423+ if ( ( fmt == 0x20 ) || ( fmt == 'g' ) )
418424 {
425+ // The general format uses the precision specifier to indicate the number of significant
426+ // digits to format. This defaults to the shortest roundtrippable string. Additionally,
427+ // given that we can't return zero significant digits, we treat 0 as returning the shortest
428+ // roundtrippable string as well.
429+
419430 isSignificantDigits = true ;
420- return precision ;
431+ return ( precision == 0 ) ? - 1 : precision ;
421432 }
422433
423- int maxDigits = precision ;
434+ return Slow ( fmt , ref precision , info , out isSignificantDigits ) ;
424435
425- switch ( fmt | 0x20 )
436+ static int Slow ( char fmt , ref int precision , NumberFormatInfo info , out bool isSignificantDigits )
426437 {
427- case 'c' :
438+ int maxDigits = precision ;
439+
440+ switch ( fmt )
441+ {
442+ case 'c' :
428443 {
429444 // The currency format uses the precision specifier to indicate the number of
430445 // decimal digits to format. This defaults to NumberFormatInfo.CurrencyDecimalDigits.
@@ -438,7 +453,7 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
438453 break ;
439454 }
440455
441- case 'e' :
456+ case 'e' :
442457 {
443458 // The exponential format uses the precision specifier to indicate the number of
444459 // decimal digits to format. This defaults to 6. However, the exponential format
@@ -456,8 +471,8 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
456471 break ;
457472 }
458473
459- case 'f' :
460- case 'n' :
474+ case 'f' :
475+ case 'n' :
461476 {
462477 // The fixed-point and number formats use the precision specifier to indicate the number
463478 // of decimal digits to format. This defaults to NumberFormatInfo.NumberDecimalDigits.
@@ -471,23 +486,7 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
471486 break ;
472487 }
473488
474- case 'g' :
475- {
476- // The general format uses the precision specifier to indicate the number of significant
477- // digits to format. This defaults to the shortest roundtrippable string. Additionally,
478- // given that we can't return zero significant digits, we treat 0 as returning the shortest
479- // roundtrippable string as well.
480-
481- if ( precision == 0 )
482- {
483- precision = - 1 ;
484- }
485- isSignificantDigits = true ;
486-
487- break ;
488- }
489-
490- case 'p' :
489+ case 'p' :
491490 {
492491 // The percent format uses the precision specifier to indicate the number of
493492 // decimal digits to format. This defaults to NumberFormatInfo.PercentDecimalDigits.
@@ -505,7 +504,7 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
505504 break ;
506505 }
507506
508- case 'r' :
507+ case 'r' :
509508 {
510509 // The roundtrip format ignores the precision specifier and always returns the shortest
511510 // roundtrippable string.
@@ -516,14 +515,15 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
516515 break ;
517516 }
518517
519- default :
518+ default :
520519 {
521520 ThrowHelper . ThrowFormatException_BadFormatSpecifier ( ) ;
522521 goto case 'r' ; // unreachable
523522 }
524- }
523+ }
525524
526- return maxDigits ;
525+ return maxDigits ;
526+ }
527527 }
528528
529529 public static string FormatFloat < TNumber > ( TNumber value , string ? format , NumberFormatInfo info )
0 commit comments