C#泛型方法中如何比对T类型与自定义类并调用对应方法
方案可行性判断
你预期里写的switch (T)的写法完全没法直接编译通过,不具备原生可行性:C# 语法不支持直接对泛型类型参数T做switch分支匹配,switch的判断值只能是基础值类型、字符串、常量值这类固定值,直接写case Contract:会直接报语法错误。
如果非要实现这个统一泛型入口的效果,可以改成类型判断的写法绕一下:
public List<T> ReadAs<T>() { List<T> result; if (typeof(T) == typeof(Contract)) { result = (List<T>)(object)ReadAsContract(); DoSomething1(); } else if (typeof(T) == typeof(Attachment)) { result = (List<T>)(object)ReadAsAttachment(); DoSomething2(); } else { throw new NotSupportedException($"暂不支持读取类型{typeof(T).Name}的数据"); } return result; }
改完的代码是可以正常运行的,但本质就是套了层泛型外壳的硬编码分支,根本没用到泛型的复用能力,属于为了泛型而泛型。
两种方案的实际选择
直接给每个类写专属的ReadAsMyClass方法,比上面那种硬凑的泛型方案靠谱得多,原因很实在:
- 没有多余的类型转换,运行性能更好
- 所有类型检查都在编译阶段完成,比如返回值类型不匹配、传参错误这类问题,写代码的时候就能被编译器揪出来,不会等到上线跑起来才抛异常
- 每个类的读取逻辑完全独立,要改Contract的字段映射、调整Attachment的读取后逻辑,直接改对应方法就行,不会碰公共逻辑影响其他类的读取
- 不用在公共方法里堆越来越多的分支判断,不会出现加了新类忘改泛型入口分支、线上直接抛不支持异常的问题
唯一的小缺点就是对外调用的时候要写对应方法名,不像泛型方法传个类型参数看起来那么统一,但这点体验差异和后期维护成本比起来完全可以忽略。
如果你的项目里只有两三个需要映射的数据库实体类,直接写专属方法的性价比最高,没必要为了看起来“高级”硬做泛型封装。如果后续实体类会越来越多,想要统一入口的话,也不建议写分支判断的假泛型,可以用反射、表达式树或者源码生成的方式做自动属性映射,省掉每个类手写读取逻辑的重复工作。
内容的提问来源于stack exchange,提问作者SSpaceRRanger
相关产品推荐
相关产品推荐

