Chciałbym spróbować przeanalizować, jeśli nie powiedzie się, następnie próbować parsować wartość o większej wydajności. Jeśli wartość wyższej pojemności przejdzie parsowanie, oznacza to, że jest poza zakresem. Jeśli to się nie uda, to jest to złe wejście.
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
}
Niestety, nie sądzę, że istnieje sposób, aby zrobić to ogólnie dla każdego typu; musisz napisać implementację dla wszystkich typów. A więc na przykład, co zrobić z Int64
? Może używać BigInteger
zamiast:
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
zmiennoprzecinkowych może być więcej zabawy, ponieważ AFAIK, nie ma „BigDecimal” i może muszą również uwzględniać wartości, które zbliżają 0 w bardzo ekstremalnych (nie pewny tego). Być może mógłbyś zmienić wariację na czeku BigInteger
, ale możesz również uwzględnić przecinki dziesiętne (najprawdopodobniej najprostsze wyrażenie byłoby tutaj najlepiej mieć tylko cyfry, opcjonalny znak ujemny i tylko najwyżej kropki dziesiętnej).Jeśli są jakieś przecinki dziesiętne, musisz je skrócić i po prostu sprawdzić całkowitą część ciągu.
EDITx2: Oto bardzo brzydki wdrożenie do sprawdzania double
wartości zbyt:
// +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
}
Ale szczerze mówiąc, w tym momencie myślę, że właśnie wyjechał na głęboką wodę. Jeśli nie masz jakiegoś realnego wąskiego gardła wydajności lub Twoja aplikacja ma wartości spoza zakresu wprowadzane często, może być lepiej, gdy tylko złapiesz je w dziwnym momencie, jak to się dzieje, jak w this answer lub, być może, po prostu, stosując regex do wejście. W moim ostatnim przykładzie mógłbym równie dobrze zrezygnować po wykonaniu regex i tak (ale nie wiem z góry, że implementacje TryParse
są łagodniejsze, co pozwala na zapis wykładniczy/naukowy. będą również musiały je pokrywać)
jest analizowanie go do większej wartości pojemności pierwszy (powiedzmy 'long' lub' uint' jeśli wiesz, że masz tylko pozytywy) następnie sprawdzanie z 'Int32.Max/MinValue' wykonalne? –
Przypuszczam, że to może być jedno rozwiązanie. Może coś bardziej ogólnego, które działałoby z dowolnym typem kontenera. – gleng
Dlaczego nie zawsze używasz największej wymaganej pojemności, jeśli jest to możliwe, że twoja wartość przepełnia mniejsze pojemności? Czy możesz dodać szczegóły dotyczące kontekstu? –