如何实现TResult由输入Lambda决定、仅指定TSource的泛型方法?
解决只指定TSource泛型参数的Interact方法问题
这问题我之前在写类似LINQ风格的方法时也踩过坑!核心原因是C#的泛型推导规则:当你显式指定部分泛型参数时,编译器不会自动推导剩余的参数——所以你原来的Interact<TSource, TResult>方法,调用时要么全靠推导(但TSource没法从lambda参数推导,因为lambda参数是TSource类型,编译器不知道具体是哪个类),要么就得同时指定两个类型参数。
要实现只指定TSource、让TResult自动推导的效果,我们可以用中间泛型类型来固定TSource,然后在后续的方法里让编译器自动识别TResult。下面是具体实现方案:
步骤1:创建一个辅助泛型类
这个类会提前绑定TSource,然后提供一个只需要推导TResult的Interact方法:
public class Interactor<TSource> { private readonly ProviderService _provider; // 构造函数接收你的服务实例 public Interactor(ProviderService provider) { _provider = provider; } // 这里只需要TResult泛型参数,编译器会自动推导 public TResult Interact(Func<TSource, TResult> lambdaCode) { // 这里放你原来Interact方法的核心逻辑 // 比如获取TSource实例(假设你的服务有获取实例的方法) TSource sourceInstance = _provider.GetSourceInstance<TSource>(); // 执行lambda并返回结果 return lambdaCode(sourceInstance); } }
步骤2:在你的ProviderService中添加入口方法
给服务添加一个泛型方法,返回上面的Interactor<TSource>实例,用来固定TSource类型:
public class ProviderService { // 新增的入口方法,只指定TSource public Interactor<TSource> For<TSource>() { return new Interactor<TSource>(this); } // 原来的双泛型方法可以保留(兼容旧调用) public TResult Interact<TSource, TResult>(Func<TSource, TResult> lambdaCode) { // 原逻辑... } }
步骤3:调用方式
现在你就可以像预期那样只指定TSource,TResult由编译器自动推导:
bool isInit = providerService.For<Foobar>().Interact(x => x.FoobarInit());
为什么这个方案可行?
通过For<Foobar>()方法,我们已经把TSource固定为Foobar,后续调用Interact时,编译器可以从lambda表达式x => x.FoobarInit()的返回值(bool)自动推导出TResult的类型,完全符合你的需求。
这种写法和LINQ的链式调用逻辑类似,既保持了代码的简洁性,又符合C#的泛型推导规则。
内容的提问来源于stack exchange,提问作者howardButcher
相关产品推荐
相关产品推荐

