需要双重转换才能将int作为对象转换为float

时间:2013-07-07 22:08:02

标签: c# object casting boxing

这是我遇到的一个奇怪的事。我有一个返回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);
}

(预先进行类型检查,永远不应使用不会评估为parseFloatfloat的表达式调用int。)是否有必要对其进行调整?双重转换这个变量?我显然不希望在所有情况下都重复使用它,因为如果parser 的返回float,则会将其截断为int首先,我们不希望这样。 (是的,我尝试将floatint替换为SingleInt32,等等。没有任何区别。)

我看到了this question,但它取决于事先知道类型,它提供的唯一解决方案就是这种双重演绎技巧,在我的情况下会截断float s,除非我做了首先进行类型检查,这还需要一个额外的局部变量来保存结果。有没有办法避免这个额外的步骤?

1 个答案:

答案 0 :(得分:6)

当您取消已放入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