2017-02-20 56 views
11

Я используюКак Decimal.Round() бросить OverflowException

Decimal.Round(decimal d) 

MSDN говорит, что может бросить OverflowException https://msdn.microsoft.com/en-us/library/k4e2bye2(v=vs.110).aspx

Я не уверен, как это может произойти. Я попытался глядя на реализацию с использованием ilSpy И получил, пока внешняя реализацию:

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

не получило ли кто-нибудь подсказку, что вход может бросить это исключение?

+5

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

+4

FWIW, [это где] (https://github.com/dotnet/coreclr/blob/32f0f9721afb584b4a14d69135bea7ddc129f755/src/classlibnative/bcltype/decimal.cpp#L175) этот целевой вызов реализован в .NET Core CLR - вы можете увидеть бросок «OverflowException» в строке 188. –

+3

И [это появляется] (https://github.com/dotnet/coreclr/blob/32f0f9721afb584b4a14d69135bea7ddc129f755/src/ palrt/decarith.cpp # L1215) для реализации «VarDecRound». На первый взгляд, я не понимаю, почему он вернет результат сбоя в «FCallRound» (в результате возникает исключение). Он либо возвращает 'E_INVALIDARG', но условие для этого уже проверено' FCallRound', или 'NOERROR', поэтому _seems_, что' OverflowException' на самом деле никогда не будет выброшено. –

ответ

3

Когда мы идем дальше от того, что вы уже обнаружили, мы закончили реализацию функции VarDecRound. Эта функция имеет ровно одну ветвь, где он возвращает код ошибки, и тогда его второй аргумент cDecimals меньше нуля. Этот аргумент указывает количество десятичных цифр раунде:

if (cDecimals < 0) 
    return E_INVALIDARG; 

(такого рода утверждение эквивалентно какая ArgumentException будет в .NET)

Как Джеймс Торп отметил в комментарии OP, аналогичное утверждение делается дальше вверх по цепочке вызовов, here:

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

Вывод:
выполнение не может достичь the point, что приведет к-й гребля OverflowException как документировано:

  1. OverflowException, кажется, были использован внутренне как броские все механизмы, так же, как OutOfMemoryException в GDI +
  2. документация не соответствует фактической реализации
  3. OverflowException не даже сделать смысл концептуально. Округление такого значения вверх или вниз в том же типе данных не может превышать integral min or max range, так как значение кандидата должен сам по себе быть в диапазоне (rounding method used)