实现List<T>后使用LINQ无法转换回自定义集合类的问题
我自定义了继承自List<Video>的VideoList类,调用Where()筛选后,没法把结果强制转回VideoList,试了网上各种方法都没解决。想知道有没有不用遍历重建集合的办法?
自定义类代码:
public class VideoList : List<Video> { public VideoList GetVideos(bool onlyShorts) => (VideoList)this.Where(x => x.IsShort.Equals(onlyShorts)).ToList(); }
运行时抛出错误:
无法将类型为“WhereListIterator1[Video]”的对象强制转换为类型“VideoList”。
原因
Where()返回的是IEnumerable<Video>,调用ToList()后生成的是原生List<Video>对象,和你的VideoList是不同的类型,强制转换必然失败——这就像不能把普通List<Video>直接转成自定义的VideoList,类型层级不匹配。
解决方案
不存在无需遍历重建的办法,因为VideoList是自定义类型,.NET框架无法自动将原生List<Video>转换为它。但可以用更简洁的方式实现重建,不用手动写遍历循环:
方法1:添加自定义构造函数
给VideoList新增一个接受IEnumerable<Video>的构造函数,利用基类的构造函数初始化集合:
public class VideoList : List<Video> { // 新增构造函数,接收IEnumerable<Video>初始化 public VideoList(IEnumerable<Video> videos) : base(videos) { } public VideoList GetVideos(bool onlyShorts) => new VideoList(this.Where(x => x.IsShort.Equals(onlyShorts))); }
这样直接用筛选后的IEnumerable<Video>创建新的VideoList,底层由框架处理遍历逻辑,代码更简洁。
方法2:使用AddRange方法
如果不想新增构造函数,也可以创建空的VideoList后用AddRange批量添加筛选结果:
public class VideoList : List<Video> { public VideoList GetVideos(bool onlyShorts) { var filteredVideos = this.Where(x => x.IsShort.Equals(onlyShorts)); var result = new VideoList(); result.AddRange(filteredVideos); return result; } }
额外建议
继承List<T>并非最佳设计实践,因为List<T>的方法都是非虚方法,无法重写。如果你的VideoList需要更多自定义行为,建议采用组合模式:内部封装一个List<Video>字段,对外暴露需要的方法和属性,这样扩展性和灵活性更强。
内容的提问来源于stack exchange,提问作者Dirk Bourgeois

