从double转换为int的最佳(最安全)方式

时间:2010-08-23 15:41:05

标签: c# type-conversion explicit tryparse

我很好奇将double转换为int的最佳方法。运行时安全是我的主要关注点(它不一定是最快的方法,但这将是我的次要问题)。我已经留下了一些我可以在下面提出的选项。任何人都可以权衡哪种是最佳做法?我还没有列出任何更好的方法来实现这个目标吗?

        double foo = 1;
        int bar;

        // Option 1
        bool parsed = Int32.TryParse(foo.ToString(), out bar);
        if (parsed)
        {
            //...
        }

        // Option 2
        bar = Convert.ToInt32(foo);

        // Option 3
        if (foo < Int32.MaxValue && foo > Int32.MinValue) { bar = (Int32)foo; }

8 个答案:

答案 0 :(得分:25)

我认为你最好的选择是:

checked
{
    try
    {
        int bar = (int)foo;
    }
    catch (OverflowException)
    {
     ...          
    }
}

来自Explicit Numeric Conversions Table

“当您从double或float值转换为整数类型时,该值将被截断。如果生成的整数值超出目标值的范围,则结果取决于溢出检查上下文。在选中的上下文中,抛出OverflowException,而在未经检查的上下文中,结果是目标类型的未指定值。“

注意:Option 2在需要时也会抛出OverflowException

答案 1 :(得分:6)

我更喜欢选项2。

您需要做的一件事是检查异常但确认它有效,就像您在选项1中检查'已解析'一样:

try
{
    bar = Convert.ToInt32(foo); 
}
catch(OverflowException)
{
    // no can do!
{

如果你要转换字符串等而不是double,你可能会得到一个'FormatException'。

修改

我最初说选项2并不比选项1特别好,@ 0xA3指出错误。选项1更糟糕,因为它在被解析为整数之前转换为字符串,这意味着效率较低。如果double超出整数范围(您可能想要或可能不想要),也不会得到OverflowException - 虽然在这种情况下'parsed'将为False。

答案 2 :(得分:5)

我意识到这不是OP要求的,但这个信息可能很方便。

以下是比较(来自http://www.dotnetspider.com/resources/1812-Difference-among-Int-Parse-Convert-ToInt.aspx

        string s1 = "1234";
        string s2 = "1234.65";
        string s3 = null;
        string s4 = "12345678901234567890123456789012345678901234567890";

        int result;
        bool success;

        result = Int32.Parse(s1);      // 1234
        result = Int32.Parse(s2);      // FormatException
        result = Int32.Parse(s3);      // ArgumentNullException
        result = Int32.Parse(s4);      // OverflowException

        result = Convert.ToInt32(s1);      // 1234
        result = Convert.ToInt32(s2);      // FormatException
        result = Convert.ToInt32(s3);      // 0
        result = Convert.ToInt32(s4);      // OverflowException

        success = Int32.TryParse(s1, out result);      // 1234
        success = Int32.TryParse(s2, out result);      // 0
        success = Int32.TryParse(s3, out result);      // 0
        success = Int32.TryParse(s4, out result);      // 0

答案 3 :(得分:3)

我会使用选项二。简短,干净,有效。

你也可以查看.Net4中的BigInteger类,你不必检查溢出。

double foo = 1;            
BigInteger bigint = new BigInteger(foo);

答案 4 :(得分:3)

我总是使用Convert类,我发现它非常优雅,方便,你可以捕获VS intellisense中定义的特定异常。

答案 5 :(得分:3)

选项3a不使用例外,总是返回一个值:

    Int32 Convert(Double d)
    {
        if (d <= (double)Int32.MinValue)
            return Int32.MinValue;
        else if (d >= (double)Int32.MaxValue)
            return Int32.MaxValue;
        else 
            return (Int32)d;
    }

答案 6 :(得分:2)

选项(1)和(2)基本上做同样的事情。选项(1)为您提供if (parsed)块,而选项(2)则为double无法表示的任何int引发错误。

选项(3)与选项(2)基本相同,除了它有额外的MinValue / MaxValue检查,而其他选项则没有。

总结:这三段代码做了不同的事情。选项(3)看起来是最强大的,因为它有一个额外的范围检查。

修改:再想一想,使用@Ani checked技巧 - 您可以免费获得范围检查。

答案 7 :(得分:2)

如果您确实需要查明是否出现问题,请使用正常演员并检查结果。

int ToInt(double foo)
{
    int result = (int)foo;
    if (foo != result)
        throw new ArgumentException()

    return result;
}

这将确保不会进行无效转换。如果可以舍入到最接近的整数,请使用Math.Round并检查结果是否在0.5之内。这将确保您的方法无法获得NaN或无穷大。