8

我有以下内容:

string outOfRange = "2147483648"; // +1 over int.MaxValue

显然,如果您有除数字以外的任何内容,这将失败:

var defaultValue = 0;
int.TryParse(outOfRange, out defaultValue);

我的问题是,因为这是一个数字,当你失败时它会失败,你int.TryParse()怎么知道它失败是因为字符串超出了它存储的容器的范围?

4

8 回答 8

4

我会选择Try/Catch这种情况的解决方案。

        string outOfRange = "2147483648";
        try
        {
            int.Parse(outOfRange);
        }
        catch (OverflowException oex)
        {

        }
        catch (Exception ex)
        { }

我知道这里的大多数人会建议避免这种情况,但有时我们只需要使用它(或者我们不必这样做,但它只会为我们节省很多时间)。
这里有一个关于效率的小帖子Try/Catch

于 2013-08-29T20:22:34.567 回答
3

可以解析为十进制然后检查范围,避免try/catch

string s = "2147483648";
decimal.Parse(s) > int.MaxValue;
于 2013-08-29T21:06:26.430 回答
2
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方法处理而不涉及异常。

这对于其他数字数据类型(如浮点数、...

于 2013-08-29T19:59:41.253 回答
2

如果失败,我会尝试解析,然后尝试解析更高容量的值。如果更高的容量值通过解析,那么您就知道它超出了范围。如果它也失败了,那就是错误的输入。

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支票进行变体,但您可能还必须考虑小数点(可能一个简单的正则表达式最好只包含数字、可选的负号和最多只有一个小数点)。如果有任何小数点,您必须将它们截断并简单地检查字符串的整数部分。

doubleEDITx2:这也是检查值的一个非常丑陋的实现:

// +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实现是否更宽松,允许指数/科学符号。如果是这样,正则表达式会也必须涵盖这些)

于 2013-08-29T20:05:30.450 回答
2

您可以尝试使用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;
}
于 2013-08-29T20:05:52.217 回答
1

使用普通Parse而不是TryParse. 然后在 try/catch 中使用它,因为它会给你适当的异常。有关详细信息,请参阅:http: //msdn.microsoft.com/en-us/library/b3h1hf19.aspx。您正在寻找的异常是OverflowException

于 2013-08-29T19:58:05.280 回答
1

我会考虑使用System.Convert.ToInt32(String)作为转换事物的机制;即因为已经为您实现了溢出异常。

这很方便,因为你可以做一些简单的事情,比如

 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);
 }   

并且逻辑已经是标准系统库的一部分。

于 2013-08-29T20:02:26.937 回答
0

直接的方法是使用Int32.Parse(string s)和 catch OverflowException;

OverflowException
s 表示小于 MinValue 或大于 MaxValue 的数字。

于 2013-08-29T19:57:03.603 回答