C# 如何将两个ConvertToDictionary重载方法合并为单个泛型方法
消除重复重载:ConvertToDictionary 泛型合并方案
当前两个ConvertToDictionary方法的执行逻辑100%重合,仅入参类型存在差异,完全可以通过泛型消除重复代码,不需要保留两个重载版本。
核心共性分析
对比现有类结构,可以提炼出两个场景的完全一致的执行逻辑依赖项:
- 两类字典类(
DgDictHosp/DgDictOper)都具备long类型的Key属性,是最终生成字典的键 - 字典类的
Data属性存放的实体(Hospitalization/Operation)都包含IDDiagnosis属性,是调用ToLiteral方法的唯一入参
基于这两个共性,就可以设计通用的泛型逻辑,不需要为每个类型单独写方法。
方案1:零侵入泛型适配(推荐优先选用,完美适配EF生成实体场景)
如果你的Hospitalization/Operation是EF自动生成的实体,不要直接修改实体文件的代码——后续在可视化设计器中调整模型、重新生成代码时,手动改动的内容会被直接覆盖。这种场景下完全可以通过泛型+委托传参的方式实现通用方法,不需要依赖任何公共基类或接口:
public static Dictionary<long, DictItem> ConvertToDictionary<TCollection, TEntity>( List<TCollection> list_g, Func<TCollection, IEnumerable<TEntity>> getDataSource, Func<TEntity, int> getDiagnosisId) { return list_g.Select(q => new DictItem { Id = q.Key, List = getDataSource(q) .Select(t => ToLiteral(getDiagnosisId(t))) .ToList() }).ToDictionary(k => k.Id); }
原有业务逻辑的调用方式只需要做极小调整,不需要改动上层分组逻辑:
- 原
GetHospDict方法内的调用替换为:var res = ConvertToDictionary( res_g, dictItem => dictItem.Data, entity => entity.IDDiagnosis); - 原
GetOperDict方法内的调用替换为:var res = ConvertToDictionary( res_g, dictItem => dictItem.Data, entity => entity.IDDiagnosis);
注意:调用时编译器会自动根据入参类型推断泛型参数,不需要手动指定泛型类型,和原有重载方法的调用体验完全一致。
方案2:强类型约束实现(适合可修改公共抽象层的长期维护场景)
如果项目中可以配套给EF实体定义抽象接口(不直接修改EF生成的类文件,而是通过partial类扩展实现接口),可以把方法的泛型约束收紧,进一步简化调用逻辑,不需要每次传委托参数:
- 先定义共性接口:
// 所有带诊断ID的实体都实现该接口 public interface IHasDiagnosis { int IDDiagnosis { get; } } // 所有字典类的公共抽象 public interface IDgDict<TEntity> where TEntity : IHasDiagnosis { long Key { get; } IEnumerable<TEntity> Data { get; } } - 通过EF的partial类机制让实体实现接口,不会被模型重新生成覆盖:
public partial class Hospitalization : IHasDiagnosis {} public partial class Operation : IHasDiagnosis {} public partial class DgDictHosp : IDgDict<Hospitalization> {} public partial class DgDictOper : IDgDict<Operation> {} - 简化后的通用泛型方法:
这种场景下调用方法时完全不需要传额外的委托参数,和原有重载方法的调用方式没有任何区别,后续如果新增其他类型的字典(比如门诊记录、急诊记录),只要实现对应接口就能直接复用方法。public static Dictionary<long, DictItem> ConvertToDictionary<TEntity>( List<IDgDict<TEntity>> list_g) where TEntity : IHasDiagnosis { return list_g.Select(q => new DictItem { Id = q.Key, List = q.Data.Select(t => ToLiteral(t.IDDiagnosis)).ToList() }).ToDictionary(k => k.Id); }
额外优化点
观察现有类结构可以发现:DgDictHosp和DgDictOper里的List属性在ConvertToDictionary的执行逻辑中从未被读取或使用,属于冗余字段,完全可以从类定义中删除,减少不必要的内存占用。
内容的提问来源于stack exchange,提问作者petr.f77
相关产品推荐
相关产品推荐

