输入功能的动态返回类型

时间:2018-03-19 20:38:55

标签: c# linq function generics func

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

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

通话应如下所示:

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

使用bool FoobarInit()作为Foobar类的一部分。

然而,我能做的最好的事情是将 TResult 定义为通用:

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

如何实现此功能调用而无需将输出类型传递给Interact调用?

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

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

providerservice拥有 Foobar 类型的实例以及许多其他实例。 我想让我们的开发人员可以在不获取实例的情况下与Foobar实例进行交互,而不是调用FoobarInit()。

e.g。在WCF场景中,这将非常有用。

开发人员应通过

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

然而,我想给他们一个方便的可能性来获得回报率, 因为这段代码给了我:

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

3 个答案:

答案 0 :(得分:0)

如果您希望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

答案 1 :(得分:0)

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

而不是像这样打电话:

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

您可以明确指定lampdaCode [sic]的参数,并让类型推断处理TResult类型:

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

答案 2 :(得分:0)

  

如何实现此功能调用而无需将输出类型传递给Interact调用?

不,let foo; try { foo = await Foo.findOne().where('bar').equals('invalid object id'); } catch (err) { foo = null; } 需要声明泛型类型Interact。事实上,正确的方法签名是:

TResult
  

电话应该是这样的

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

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

c#编译器有一个非常好的类型推理算法,使用它,不需要在你的调用中明确指定泛型类型。

现在,在您的特定情况下,您可能会遇到模糊的通话问题:

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

好的,那么class Foo { public bool Frob() { ... } } class Blah { public int Frob() { ... } } var res = providerService.Interact(x => x.Frob()); 现在是什么? x?您可以通过明确声明lambda参数的类型来轻松解决此问题:

res

现在,编译器会自行推断var res = providerService.Interact((Blah x) => x.Frob()); TSourceBlahTResult

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