I would attempt to parse, if it fails, then attempt to parse a higher-capacity value. If the higher capacity value passes parsing, then you know it's out of range. If it fails as well, then it's bad input.
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
}
Unfortunately, I don't think there's a way to do this generically for any type; you'd have to write an implementation for all types. So for example, what do do for Int64
? Maybe use BigInteger
instead:
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
}
EDIT: double
floating point values may be more fun since AFAIK, there's no "BigDecimal" and you may have to also account for values that approach 0 at the very extreme (not sure about that). Possibly you could do a variation on the BigInteger
check but you might also have to account for decimal points (probably a simple regex would be best here to have only numbers, an optional negative sign, and only one at most decimal point). If there are any decimal points, you'd have to truncate them out and simply check the integer portion of the string.
EDITx2: Here's a pretty ugly implementation for checking double
values too:
// +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
}
But honestly, at this point I think we've just gone off the deep end. Unless you have some real performance bottleneck, or your application has out-of-range values inputted frequently, you might be better off just catching them the odd time it happens as in this answer or perhaps more simply, applying a regex to the input. In my last example, I may have as well just quit after doing the regex anyway (but I don't know off the top of my head if the TryParse
implementations are more lenient, allowing for exponential/scientific notation. If so, the regex would have to cover these as well)
long
, oruint
if you know you only have positives) then checking againstInt32.Max/MinValue
viable? – LindonTry-Catch
and inspecting the exception message instead ofint.TryParse
– Syllepsisint
,double
,long
?) – LindonTryParse
won't throw an exception. (plus it's bad form to use exceptions as a control flow device) EDIT: Ahh, sorry, didn't realize you meantInt32.Parse
. Yeah, that might work especially if you don't expect out-of-range values often at all. EDITx2: Just to clarify, if you expect to have out-of-range values often, I think you'd be better off avoiding the try/catch option electing to better handle it. – LindonParse
methods instead to allow exceptions to occur, perhaps? Just a curiosity of mine & observation. – Stopint
overflows at +- 2billion? The use cases should determine the actual range of input you're expecting, and you would write your validation depending on that range, and you would also choose the appropriate data-type. – Gombroon