我喜欢用 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指令或程序集引用?)
答案 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());
}
不需要任何类型参数。
答案 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());
为TSource
且Blah
为TResult
。
长话短说,c#不允许部分泛型类型推断,但在你的场景中你不需要它。您可以通过简单地声明lambda表达式中的类型来实现int
和TSource
的完全推断。