2017-02-20 4 views
11

J'utiliseComment Decimal.Round() jeter OverflowException

Decimal.Round(decimal d) 

MSDN dit qu'il peut jeter OverflowException https://msdn.microsoft.com/en-us/library/k4e2bye2(v=vs.110).aspx

Je ne sais pas comment cela peut se produire. J'ai essayé à la recherche sur la mise en œuvre à l'aide ilSpy et obtenu jusqu'à ce que la mise en œuvre externe de:

// decimal 
[SecurityCritical] 
[MethodImpl(MethodImplOptions.InternalCall)] 
private static extern void FCallRound(ref decimal d, int decimals); 

Quelqu'un a une idée de ce que l'entrée peut lancer cette exception?

+5

http://stackoverflow.com/questions/3203959/overflow- exception-when-divisant-two-decimals-in-net – Equalsk

+4

FWIW, [ceci est où] (https://github.com/dotnet/coreclr/blob/32f0f9721afb584b4a14d69135bea7ddc129f755/src/classlibnative/bcltype/decimal.cpp#L175) cet appel cible est implémenté dans le .NET Core CLR - vous pouvez voir le lancement de 'OverflowException' sur la ligne 188. –

+3

Et [ceci apparaît] (https://github.com/dotnet/coreclr/blob/32f0f9721afb584b4a14d69135bea7ddc129f755/src/ palrt/decarith.cpp # L1215) être la mise en œuvre de 'VarDecRound'. À première vue, je ne vois pas pourquoi il retournerait un résultat non 'FCallRound' (entraînant l'exception levée). Il soit elle retourne 'E_INVALIDARG', mais la condition qui a déjà été vérifiée par' FCallRound' ou 'NOERROR', il _seems_ que le' OverflowException' ne devrait pas en fait jamais être jeté. –

Répondre

3

Quand nous allons plus loin de ce que vous avez déjà vous découvert, nous nous retrouvons dans la mise en œuvre de la fonction VarDecRound. Cette fonction a exactement une branche où il renvoie un code d'erreur, et qui est en son second argument cDecimals est plus petit que zéro. Cet argument indique le nombre de chiffres décimaux pour arrondir à:

if (cDecimals < 0) 
    return E_INVALIDARG; 

(ce genre d'affirmation est l'équivalent de ce qu'un ArgumentException serait dans .NET)

Comme James Thorpe a souligné dans un commentaire sur OP, une affirmation similaire est fait en amont de la chaîne d'appel, here:

if (decimals < 0 || decimals > 28) 
    FCThrowArgumentOutOfRangeVoid(...) 

Conclusion:
exécution ne peut pas atteindre the point qui entraînerait e ramer le OverflowException comme documenté:

  1. OverflowException semble avoir été utilisé en interne comme un fourre-tout mécanisme, tout comme OutOfMemoryException dans GDI +
  2. La documentation ne correspond pas à la mise en œuvre effective
  3. OverflowException ne même pas faire sens conceptuellement. Pour compléter une mise en valeur ou vers le bas dans le même type de données ne peut pas dépasser éventuellement un integral min or max range, parce que la valeur candidate doit être lui-même dans la gamme (rounding method used)