为什么C#编译器不能从函数签名推断泛型类型的委托? [英] Why can't C# compiler infer generic-type delegate from function signature?

查看:139
本文介绍了为什么C#编译器不能从函数签名推断泛型类型的委托?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用一个函数,它将两个函数作为参数,并返回一个新的函数:

  public static动作及LT; T>撰写< T>(Action< T> first,Action second)
{
return new Action< T>(arg =>
{
first(arg);
秒();
});
}

我注意到如果我没有指定 T 时,发送一个静态或成员函数(而不是实际的动作< T> 对象):

  static void Main(string [] args)
{
//编译器错误
var = Compose(Test,()=> Console.WriteLine(world));
组合(hello);

Console.ReadLine();


public static void Test(string arg)
{
Console.Write(arg);
}

错误信息:


方法'ConsoleTest.Program.Compose(System.Action,System.Action)'的参数不能从用法中推断出来。尝试明确指定类型参数。


我的问题:为什么不能在此推断类型参数? Test 的签名在编译时已知,不是吗?是否真的有一些函数可以替代 Test ,这会导致它的签名模糊不清?



脚注:我知道我只需发送新的Action (Test)而不是 Test 撰写(如这个问题所述) - 我的问题是为什么,而不是我怎么能做到这一点。 至少从编译器的角度来看, Test 实际上是一个方法组,直到编译器确定它将具有的参数类型为止。即使组中只有一个方法(在当前作用域中只有一个 Test 方法),也是如此。



观察:

  var composed =撰写< object>(Test,()=> Console.WriteLine(world )); 

会产生错误:


匹配'编写< object>(System.Action< object>,System.Action)'的最佳重载方法匹配有一些无效参数



参数1:无法从'方法组'转换为' System.Action< object> '


但是这很好:

  var composed =撰写< string>(Test,()=> Console.WriteLine(world)); 

我的猜测是编译器看到了方法组表达式( Test ),并且从某种意义上隐式地键入泛型方法调用( Compose )为'unbound'。它不能完全确定从方法组中从参数类型的'未绑定'签名到 Compose 选择哪种方法,并且它无法确定哪种类型类型来自签名的撰写的参数。它需要一个或另一个绑定,以编制整个陈述。

I'm working with a function that takes two functions as parameters, and returns a new composed one:

public static Action<T> Compose<T>(Action<T> first, Action second)
{
    return new Action<T>(arg =>
    {
        first(arg);
        second();
    });
}

I've noticed that the compiler complains if I don't specify T, when sending it a static or member function (as opposed to an actual Action<T> object):

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);
}

The error message:

The arguments for method 'ConsoleTest.Program.Compose(System.Action, System.Action)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

My question: Why can't the type argument be inferred here? The signature of Test is known at compile time, is it not? Is there really some function you could put in place of Test, that would cause its signature to be ambiguous?

Footnote: I know I can simply send new Action<string>(Test) instead of Test to Compose (as noted in this question) -- my question is "why", not "how can I do this".

解决方案

I suppose it probably has something to do with the fact that, at least from the compiler's perspective, Test is actually a 'method group' until the compiler has determined what it types of parameters it will have. This is true even if there is only one method in the group (only one Test method in the current scope).

Observe:

var composed = Compose<object>(Test, () => Console.WriteLine(" world"));

yields the error:

The best overloaded method match for 'Compose<object>(System.Action<object>, System.Action)' has some invalid arguments

Argument 1: cannot convert from 'method group' to 'System.Action<object>'

But this is fine:

var composed = Compose<string>(Test, () => Console.WriteLine(" world"));

My guess is that the compiler see the both method group expression (Test) and implicitly typed generic method invocation (Compose) as 'unbound' in a sense. It can't fully determine which method to select from the method group from the type 'unbound' signature of the parameter to Compose, and it can't determine which the type type parameter for Compose from the signature. It needs one or the other to be 'bound' in order to compile the whole statement.

这篇关于为什么C#编译器不能从函数签名推断泛型类型的委托?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆