McG*_*gle 7 c# generics functional-programming type-inference currying
我正在使用一个函数,它接受两个函数作为参数,并返回一个新的组合函数:
public static Action<T> Compose<T>(Action<T> first, Action second)
{
return new Action<T>(arg =>
{
first(arg);
second();
});
}
Run Code Online (Sandbox Code Playgroud)
我注意到编译器抱怨如果我没有指定T,当发送静态或成员函数(而不是实际Action<T>对象)时:
static void Main(string[] args)
{
// compiler error here
var composed = Compose(Test, () => Console.WriteLine(" world"));
composed("hello");
Console.ReadLine();
}
public static void Test(string arg)
{
Console.Write(arg);
}
Run Code Online (Sandbox Code Playgroud)
错误消息:
无法从用法中推断出方法'ConsoleTest.Program.Compose(System.Action,System.Action)'的参数.尝试显式指定类型参数.
我的问题:为什么不能在这里推断出类型论证?签名Test是在编译时知道的,不是吗?是否真的有一些功能可以代替Test,这会导致它的签名含糊不清?
附注:我知道我可以简单地发送new Action<string>(Test),而不是Test到Compose(在注意这个问题) -我的问题是"为什么",而不是"我怎样才能做到这一点."
我想它可能与以下事实有关:至少从编译器的角度来看,Test实际上是一个'方法组',直到编译器确定它将具有哪些类型的参数.即使组中只有一个Test方法(当前范围中只有一个方法),也是如此.
注意:
var composed = Compose<object>(Test, () => Console.WriteLine(" world"));
Run Code Online (Sandbox Code Playgroud)
产生错误:
'
Compose<object>(System.Action<object>, System.Action)' 的最佳重载方法匹配有一些无效的参数参数1:无法从'方法组'转换为'
System.Action<object>'
但这很好:
var composed = Compose<string>(Test, () => Console.WriteLine(" world"));
Run Code Online (Sandbox Code Playgroud)
我的猜测是编译器在某种意义上将两个方法组表达式(Test)和隐式键入的泛型方法调用(Compose)视为"未绑定".它无法完全确定从参数类型的"未绑定"签名中选择方法组中的哪个方法Compose,并且无法Compose从签名中确定哪个类型类型参数.它需要一个或另一个'绑定'才能编译整个语句.