C#向集合添加Student对象时出现IEnumerable类型转换失败异常
异常原因
你遇到的运行时类型转换异常由多处代码逻辑错误引发,直接触发报错的是单个实体对象被强制转换为集合类型的错误写法,具体问题点如下:
- 触发报错的直接原因:
Student是普通实体类,未实现IEnumerable<Student>接口,AddStudent方法中(IEnumerable<Student>)st的写法是将单个学生实例硬转为学生集合,运行时无法完成类型转换,直接抛出你看到的异常。 - 集合操作逻辑错误:
IEnumerable的Concat方法不会修改原集合,只会返回拼接后的新集合;原代码调用Concat后未将返回值赋值回students字段,就算类型转换正确,新增的学生也不会被存入集合。同时原代码中students字段未初始化,默认值为null,调用集合方法时还会触发空引用异常。 - 额外的类型转换隐患:
GetAllStudents、GetStudentsForGrade两个方法中,直接将IEnumerable<Student>强转为IEnumerable<string>,Student类型与string类型无继承/实现关系,该强转同样会在运行时抛出异常。且原代码未实现需求要求的排序规则:全量列表需按年级升序排列,同年级学生按姓名升序排列。
修复方案
- 存储学生数据的字段不要用不可变的
IEnumerable<Student>,替换为已初始化的List<Student>,直接调用Add方法存入新学生,从根源上避免单个对象转集合的错误写法,同时解决集合未初始化、拼接结果不生效的问题。 - 移除所有无效的强转逻辑,需要返回学生姓名字符串集合时,通过LINQ的
Select方法投影取Student的Name属性即可。 - 按需求补全排序逻辑:查询全量学生时先按年级升序排序,再按姓名升序排序;查询指定年级学生时,结果按姓名升序排序。
修复后的可运行代码如下:
using System.Collections.Generic; using System.Linq; namespace Ex02_School { public class School { // 初始化私有可变学生集合,符合封装原则 private readonly List<Student> _students = new List<Student>(); public void AddStudent(string studentName, int grade) { _students.Add(new Student(studentName, grade)); } public IEnumerable<string> GetAllStudents() { return _students .OrderBy(student => student.Grade) .ThenBy(student => student.Name) .Select(student => student.Name); } public IEnumerable<string> GetStudentsForGrade(int grade) { return _students .Where(student => student.Grade == grade) .OrderBy(student => student.Name) .Select(student => student.Name); } } public class Student { public string Name; public int Grade; public Student(string name, int grade) { Name = name; Grade = grade; } } }
内容的提问来源于stack exchange,提问作者Ignacio Sierro
相关产品推荐
相关产品推荐

