来自输入函数的动态 return 类型

Dynamic return type from input function

我喜欢用 TResult 实现一个方法取决于输入函数 lampdacode 的 return 值(就像System.Linq.Select) 例如:

public TResult Interact<TSource> (Func<TSource, TResult> lampdaCode)

调用应如下所示:

bool isInit = providerService.Interact<Foobar>(x => x.FoobarInit());

将 bool FoobarInit() 作为 Foobar 的一部分 class。

但是我能做的最好的事情就是将 TResult 定义为通用的:

public TResult Interact<TSource, TResult> (Func<TSource, TResult> lampdaCode)

关于如何在无需将输出类型传递到 Interact 调用的情况下实现此功能调用的任何想法?

编辑: 好吧,我想我还不够清楚:

providerService.Interact<Foobar>(x => x.FoobarInit());

providerservice 拥有一个 Foobar 类型的实例和许多其他实例。 我想为我们的开发人员提供无需获取实例并调用 FoobarInit() 即可与 Foobar 实例交互的可能性。

例如在 WCF 场景中,这将非常有用。

开发人员应通过

与 foobar 实例交互
providerService.Interact<Foobar>(x => x.FoobarInit());

不过我想给他们一个方便的机会来接收 return 值, 因为这段代码给了我:

错误 CS0246 找不到类型或命名空间名称 'TResult'(是否缺少 using 指令或程序集引用?)

如果您希望 Interact 能够从签名中嗅出类型,您必须至少在某个地方提供它。现在它不知道 x 是一个 Foobar,所以它不能推断出任何关于调用的信息。

也许最简单的地方是在 lambda 的参数列表中,如下例所示。

class ProviderService
{
    public TResult Interact<TInput,TResult> (Func<TInput, TResult> lambdaCode)  where TInput : class, new()
    {
        var x = new TInput();
        Initialize(x); //or whatever
        return lambdaCode(x);
    }
}

public static void Test()
{
    var providerService = new ProviderService();
    var isInit = providerService.Interact((Foobar x) => x.FoobarInit());
}

不需要类型参数。

Check Example2 in my DotNetFiddle for proof

据我所知,C# 不支持部分泛型类型推断。您可以使用中间通用包装器 class 一次将实例化减少为一种类型,但这并不理想。

而不是这样调用:

bool isInit = providerService.Interact<Foobar>(x => x.FoobarInit());

您可以显式指定 lampdaCode [原文如此] 的参数并让类型推断处理 TResult 类型:

bool isInit = providerService.Interact((Foobar x) => x.FoobarInit());

Any ideas how to achieve this functional call without the need to pass the output type into the Interact call?

不行,Interact需要声明泛型TResult。正确的方法签名实际上是:

public TResult Interact<TSource, TResult> (
    Func<TSource, TResult> lampdaCode)

The call should look like this

不应该,理想情况下应该是这样的:

var isInit = providerService.Interact(x => x.FoobarInit());

c# 编译器有一个非常好的类型推断算法,好好利用它,调用时无需显式指定泛型类型。

现在,在您的特定情况下,您很可能 运行 遇到了模棱两可的调用问题:

class Foo { public bool Frob() { ... } } 
class Blah { public int Frob() { ... } }

var res = providerService.Interact(x => x.Frob());

好的,现在 x 是多少?还有 res?您可以通过显式声明 lambda 参数的类型轻松解决此问题:

var res = providerService.Interact((Blah x) => x.Frob());

现在编译器会自己推理出 TSourceBlahTResultint.

长话短说,c# 不允许部分泛型类型推断,但在您的方案中不需要它。您可以通过简单地在 lambda 表达式中声明类型来实现 TSourceTResult 的完全推断。