您的位置:首页 > 其它

LINQ表达式中关于显式范围变量的Bug

2008-02-16 23:07 302 查看
MSDN博客中的一篇文章提到了.NET 3.5 SP1会带来的处个修正,见以下代码:

var floats = new ArrayList { 2.5f, 3.5f, 4.5f };

var ints = from int i in floats
select i;

注意from后面声明的显式类型(int)。开发者会很自然地认为ints为[2,3,4],但在现在版本.NET 3.5环境下得到的却是[2,4,4]。

原来那段LINQ表达式将会被编译为以下方法调用:

var ints = floats.Cast<int>().Select<int,int>(i => i);

问题便出现在Cast这个扩展方法中,而Cast内部是通过调用Convert类的ToInt32方法转换ArrayList中元素类型的,而这个方法既不是对浮点数进行截去小数,也不是简单的round:
ToInt32方法的文档中是这样描述返回值的:

value rounded to the nearest 32-bit signed integer. If value is halfway
between two whole numbers, the even number is returned; that is, 4.5 is
converted to 4, and 5.5 is converted to 6.

这种数值转换的方式被称为Banker's rounding

这是个程序语义的问题,将在以后的.NET Frameworkk 3.5 SP1中解决,估计只是修改Cast方法的实现。现在的应对方法是在一些应用场景中不使用显式范围变量。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: