Скажите, если строка для double / float/int / short / byte находится вне диапазона
У меня есть следующее:
string outOfRange = "2147483648"; // +1 over int.MaxValue
Очевидно, что если у вас есть что-то, кроме числа, это не сработает:
var defaultValue = 0;
int.TryParse(outOfRange, out defaultValue);
Мой вопрос таков: поскольку это число, и оно не сработает, когда вы int.TryParse()
, Как вы можете сказать, что оно не сработало, потому что строка вышла за пределы контейнера, в котором она хранится?
8 ответов:
Я попытаюсь проанализировать, если это не удастся, затем попытаюсь проанализировать значение более высокой емкости. Если более высокое значение емкости проходит синтаксический анализ, то вы знаете, что оно находится вне диапазона. Если он также терпит неудачу,то это плохой ввод.
К сожалению, я не думаю, что есть способ сделать это обобщенно для любого типа; вам придется написать реализацию для всех типов. Так, например, что делать дляstring outOfRange = "2147483648"; // +1 over int.MaxValue int result; if (!Int32.TryParse(outOfRange, out result)) { long rangeChecker; if (Int64.TryParse(outOfRange, out rangeChecker)) //out of range else //bad format }
Int64
? Может быть, использоватьBigInteger
вместо:string outOfRange = "9223372036854775808"; // +1 over Int64.MaxValue long result; if (!Int64.TryParse(outOfRange, out result)) { BigInteger rangeChecker; if (BigInteger.TryParse(outOfRange, out rangeChecker)) //out of range else //bad format }
Редактировать:
double
значения с плавающей запятой могут будьте веселее, так как AFAIK, там нет "BigDecimal", и вы можете также учитывать значения, которые приближаются к 0 в самом крайнем случае (не уверен в этом). Возможно, вы могли бы сделать вариацию на проверкуBigInteger
, но вам также придется учитывать десятичные точки (вероятно, простое регулярное выражение будет лучше здесь иметь только числа, необязательный отрицательный знак и только одну, самое большее десятичную точку). Если есть какие-либо десятичные точки, вы должны были бы усечь их и просто проверить целочисленная часть строки.EDITx2: вот довольно уродливая реализация для проверки значений
double
:Но, честно говоря, на данный момент я думаю, что мы просто сошли с ума. Если у вас нет какого-то реального узкого места производительности, или ваше приложение имеет значения вне диапазона, вводимые часто, Вам может быть лучше просто поймать их нечетное время, как это происходит в этом ответе или, возможно, более просто, применяя регулярное выражение к входным данным. В моем последнем примере я мог бы также просто бросить делать регулярное выражение в любом случае (но я не знаю, с моей головы, являются ли реализации// +bajillion over Double.MaxValue string outOfRange = "90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.1"; double result; if (!Double.TryParse(outOfRange, out result)) { string bigIntegerInput = outOfRange; if (!Regex.IsMatch(bigIntegerInput, @"^-?[0-9]\d*(\.\d+)?$")) //bad format int decimalIndex = bigIntegerInput.IndexOf('.'); if (decimalIndex > -1) bigIntegerInput = bigIntegerInput.Substring(0, decimalIndex); BigInteger rangeChecker; if (BigInteger.TryParse(bigIntegerInput, out rangeChecker)) //out of range else //bad format }
TryParse
более мягкими, позволяя экспоненциальную / научную нотацию. Если это так, регулярное выражение должно было бы охватить и их)
Я бы пошел с решением
Try/Catch
для этого сценария.Я знаю, что большинство людей здесь рекомендовали бы избегать этого, но иногда мы просто должны использовать его (или мы не должны, но это просто сэкономит нам много времени).string outOfRange = "2147483648"; try { int.Parse(outOfRange); } catch (OverflowException oex) { } catch (Exception ex) { }
вот небольшой пост об эффективностиTry/Catch
.
Может разобрать до десятичной, а затем проверить диапазон, избегает try / catch
string s = "2147483648"; decimal.Parse(s) > int.MaxValue;
string outOfRange = "2147483648"; // +1 over int.MaxValue int value; if(! int.TryParse(outOfRange, out value)) { try { int.Parse(defaultValue); } catch(OverflowException e) { // was overflow } catch(Exception e) { // was other reason } }
Предполагая, что существует несколько случаев, когда число слишком велико, накладные расходы на выбрасывание и перехват исключений могут быть терпимыми, поскольку обычные случаи обрабатываются более быстрым методом
TryParse
без привлечения исключений.Это будет работать аналогично для других числовых типов данных, таких как floats, ...
Можно попробовать выполнить синтаксический анализ с помощью
BigInteger
.BigInteger bigInt; bool isAnOutOfRangeInt = BigInteger.TryParse(input, out bigInt) && (bigInt > int.MaxValue || bigInt < int.MinValue); // if you care to have the value as an int: if (!isAnOutOfRangeInt) { int intValue = (int)bigInt; }
Используйте обычный
Parse
вместоTryParse
. А затем используйте его внутри try / catch, потому что он даст вам соответствующее исключение. Смотрите это для деталей: http://msdn.microsoft.com/en-us/library/b3h1hf19.aspx исключение, которое вы ищете, - этоOverflowException .
Я бы посмотрел на использование системы .Преобразовать.ToInt32 (String) как механизм для преобразования вещей; а именно потому, что OverflowException уже был реализован для вас.
Это удобно, потому что вы можете сделать что-то простое, например
try { result = Convert.ToInt32(value); Console.WriteLine("Converted the {0} value '{1}' to the {2} value {3}.", value.GetType().Name, value, result.GetType().Name, result); } catch (OverflowException) { Console.WriteLine("{0} is outside the range of the Int32 type.", value); } catch (FormatException) { Console.WriteLine("The {0} value '{1}' is not in a recognizable format.", value.GetType().Name, value); }
И логика уже является частью стандартной системной библиотеки.
Прямым путем было бы вместо этого использовать Int32.Parse (string s) и catch
OverflowException
;OverflowException
s представляет собой число меньше, чем minvalue или больше, чем maxvalue.