为何C#中double转int直接赋值报错,foreach遍历却不报错?如何触发编译失败?
问题解答
为何两者处理逻辑不同?
直接赋值和foreach循环的类型转换规则存在差异:
- 直接赋值时,
double转int属于收缩转换(会丢失小数部分精度),C#禁止这种转换隐式执行,必须手动编写显式转换(int)x,否则触发CS0266错误。 - 而
foreach遍历泛型集合时,若循环变量类型和集合元素类型不同,编译器会自动检查是否存在显式转换。如果存在,就会自动插入显式转换代码,你的代码实际等价于:
显式转换是C#允许的操作,因此这段代码能正常编译。double x = 0; ReadOnlyCollection<double> y = new ReadOnlyCollection<double>(new double[3] { 1.23, 2.34, 3.45 }); foreach (double item in y) { int z = (int)item; x += z; }
如何让foreach代码触发编译失败?
如果希望遍历IEnumerable时的类型转换和直接赋值规则一致,有两种可行方式:
方式1:拆分转换步骤,手动暴露隐式转换
把循环中的类型转换单独抽离出来,不让编译器自动插入显式转换:
double x = 0; ReadOnlyCollection<double> y = new ReadOnlyCollection<double>(new double[3] { 1.23, 2.34, 3.45 }); foreach (var item in y) { int z = item; // 此处会触发CS0266错误,和直接赋值规则完全一致 x += z; }
方式2:启用代码分析规则强制类型匹配
启用CA1830规则(要求泛型集合的foreach循环迭代变量类型与集合元素类型严格匹配),并将该规则设置为编译错误。这样只要循环变量类型和集合元素类型不匹配,就会在编译阶段直接报错。
内容的提问来源于stack exchange,提问作者Sebastian Wouters
相关产品推荐
相关产品推荐

