这是我遇到的一个奇怪的事。我有一个返回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
或float
的表达式调用int
。)是否有必要对其进行调整?双重转换这个变量?我显然不希望在所有情况下都重复使用它,因为如果parser
的返回为float
,则会将其截断为int
首先,我们不希望这样。 (是的,我尝试将float
和int
替换为Single
和Int32
,等等。没有任何区别。)
我看到了this question,但它取决于事先知道类型,它提供的唯一解决方案就是这种双重演绎技巧,在我的情况下会截断float
s,除非我做了首先进行类型检查,这还需要一个额外的局部变量来保存结果。有没有办法避免这个额外的步骤?
答案 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