从作为对象的int转换为float需要双重强制转换

本文关键字:转换 float 对象 int | 更新日期: 2023-09-27 18:21:29

这是我遇到的一个奇怪的。我有一个函数,它返回一个object。在特定情况下,我确信对象是int,但另一个调用此函数的函数需要float。我唯一能做到这一点的方法是:

private object parser(string expr) {...}
private float parseFloat(string expr)
{
    ...
    object result = parser(expr);
    if (result is int)
        return (float)(int)result;
    else
        return (float)result;
}

如果没有这种类型检查,我根本无法让它工作,尽管我知道在这种情况下解析器函数的结果是int。(你可以在调试器中看到它。)我更喜欢简单的一行:

private float parseFloat(string expr)
{
    ...
    return (float)parser(expr);
}

(类型检查是事先完成的,parseFloat永远不应该用不会计算为floatint的表达式调用。)是否有必要对该变量进行双重强制转换?我显然不想在所有情况下都对其进行双重强制转换,因为如果parser的返回是float,它会首先将其截断为int,我们不希望这样。(是的,我试着用SingleInt32等替换floatint。没有任何区别。)

我看到了这个问题,但这取决于提前知道类型,它提供的唯一解决方案是这种双铸技巧,在我的情况下,除非我先进行类型检查,否则会截断floats,这也需要一个额外的局部变量来保存结果。有什么办法可以避免这一额外的步骤吗?

从作为对象的int转换为float需要双重强制转换

当您取消装箱已放入object框中的值类型时,必须使用正确的强制转换。从一种数字类型到另一种类型的转换是取消装箱后的额外强制转换。

然而,在您的情况下,第二个强制转换实际上是隐式的,因此您可以将其简化为:

if (result is int)
    return (int)result;
else
    return (float)result;

为什么首先要将值类型装箱?如果你不知道盒子里装的是什么类型的,要想打开盒子,你通常必须像往常一样用is进行检查。

但是,请注意,对于像这些内置数字类型这样的(IConvertible)类型,您也可以使用Convert类,因此:

return Convert.ToSingle(result);

它看起来更漂亮,但我不认为它更快。它可能会进行相同类型的检查。

如果parser只给出数字类型,并且出于某种原因,您坚持将这些值类型装箱,那么您不妨将它们装箱为IConvertible,这样就需要更改返回类型,如下所示:

private IConvertible parser(string expr) {...}

然后你的代码可以这样:

IConvertible result = parser(expr);  // it's some number boxed in an IConvertible reference type
return result.ToSingle(null);  // instance method in IConvertible