C# 校验List<CubeReportRow>存在指定RowName元素避免重复添加的方法
问题根因
List<CubeReportRow>内置的Contains()方法,只能匹配集合内存储的CubeReportRow类型实例。直接传入字符串类型的rowName时,因为参数类型不匹配,编译器自然会抛出“无法将string转换为CubeReportRow”的报错。- 写
!rows.Contains(row[0])时没有编译报错,是因为row[0]是object类型,满足方法的入参要求,但方法内部是按CubeReportRow的类型做相等性匹配,和传入的字符串值永远不可能相等,所以判断逻辑完全失效,根本拦不住重复行。
可行的实现方案
方案1:最小改动适配现有逻辑(小数据量首选)
不需要调整原有类结构,直接把循环里的判断行换成按属性匹配的LINQ查询就行:
// 替换原循环中的 if (!rows.Contains(rowName)) if (!rows.Any(r => r.RowName == rowName))
这个写法直接检查rows集合中是否存在RowName属性和当前DataTable行的rowName相等的元素,逻辑完全匹配去重需求。缺点是每次判断都会全量遍历整个列表,当数据量超过万级时会有明显的性能损耗。
方案2:大数据量优化实现
如果处理的DataTable行数较多,反复遍历列表会产生不必要的性能开销,可以额外维护一个HashSet<string>记录已经存在的RowName,把查找复杂度从O(n)降到O(1),核心改动如下:
public virtual IList<CubeReportRow> TransformResults(CubeReport report, DataTable dataTable) { if (dataTable.Rows.Count == 0 || dataTable.Columns.Count == 0) return new List<CubeReportRow>(); var rows = new List<CubeReportRow>(); // 新增辅助集合,存储已存在的RowName做快速查找 var existingRowNames = new HashSet<string>(); var columns = columnTransformer.GetColumns(dataTable); foreach (DataRow row in dataTable.Rows) { var rowName = row[0].ToString(); // 直接查哈希表判断是否重复,速度远快于遍历列表 if (!existingRowNames.Contains(rowName)) { var values = cubeReportValueFactory.CreateCubeReportValuesForRow(dataTable, row, rowName, columns, report); var reportRow = new CubeReportRow(row[3].ToString(), row[2].ToString(), row[1].ToString(), values); // 新增有效行时,同步更新辅助集合 existingRowNames.Add(rowName); rows.Add(reportRow); } } return rows; }
额外提醒:从你贴的类定义看,
CubeReportRow目前只定义了3个属性,但实例化时传了4个构造参数,记得补全和构造函数匹配的属性定义,避免后续运行时出现赋值异常。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

