来自输入函数的动态 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());
}
不需要类型参数。
据我所知,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());
现在编译器会自己推理出 TSource
是 Blah
而 TResult
是 int
.
长话短说,c# 不允许部分泛型类型推断,但在您的方案中不需要它。您可以通过简单地在 lambda 表达式中声明类型来实现 TSource
和 TResult
的完全推断。
我喜欢用 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());
}
不需要类型参数。
据我所知,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());
现在编译器会自己推理出 TSource
是 Blah
而 TResult
是 int
.
长话短说,c# 不允许部分泛型类型推断,但在您的方案中不需要它。您可以通过简单地在 lambda 表达式中声明类型来实现 TSource
和 TResult
的完全推断。