C# 编译器可以';传递方法时,请不要找出泛型类型

C# 编译器可以';传递方法时,请不要找出泛型类型,c#,generics,c#-4.0,C#,Generics,C# 4.0,我在C#和泛型类型推断方面遇到了问题。 我想编写一个方法,该方法通过一个具有任何类型的方法传递,但编译器无法推断我传递的方法的类型。编译器总是抱怨消息 需要一个带“??”的方法???TestFunc(???,?)签名 这里有一个测试用例 using System; public class Example { private interface ITest { int TestFunc(string str, int i); } private

我在C#和泛型类型推断方面遇到了问题。 我想编写一个方法,该方法通过一个具有任何类型的方法传递,但编译器无法推断我传递的方法的类型。编译器总是抱怨消息

需要一个带“??”的方法???TestFunc(???,?)签名

这里有一个测试用例

using System;

public class Example
{
    private interface ITest
    {
        int TestFunc(string str, int i);
    }

    private class Test : ITest
    {
        public int TestFunc(string str, int i) { return 0; }
    }

    public static void Main()
    {
        ITest t = new Test();
        DoWork(t.TestFunc);
    }

    public static void DoWork<T1, T2, TResult>(Func<T1, T2, TResult> func)
    {
    }
}
使用系统;
公开课范例
{
专用接口测试
{
int TestFunc(字符串str,int i);
}
私有类测试:ITest
{
public int TestFunc(string str,int i){return 0;}
}
公共静态void Main()
{
ITest t=新测试();
道工(t.TestFunc);
}
公共静态无效工作(Func Func)
{
}
}

有人能解释一下问题出在哪里吗?

我假设编译器在这种情况下不会尝试推断类型,因为如果您有TestFunc的重载,则所需的行为没有得到很好的定义。考虑:

    private class Test 
    {
        public int TestFunc(string str, int i) { return 0; }
        public int TestFunc(string str, long i) { return 0; }
    }

    public static void Main()
    {
        Test t = new Test();
        DoWork(t.TestFunc);
    }

    public static void DoWork<T1, T2, TResult>(Func<T1, T2, TResult> func)
    {
    }
私有类测试
{
public int TestFunc(string str,int i){return 0;}
public int TestFunc(string str,long i){return 0;}
}
公共静态void Main()
{
测试t=新测试();
道工(t.TestFunc);
}
公共静态无效工作(Func Func)
{
}

不幸的是,类型推断的规则极其复杂。至少,我发现它们很复杂,我相信Eric和Mads正在为下一个版本的规范简化它们——很可能不是改变实现的内容,而是改变规范中表达的方式

在这种情况下,根本的问题是方法组的参数类型不参与类型推断,即使返回类型参与。特别是,根据C#4规范的7.5.2.6:

否则,如果E是方法组,T是委托类型或表达式树类型,参数类型为T1…Tk,返回类型为Tb,并且E的重载解析类型为T1…Tk,则生成返回类型为U的单个方法,则从U到Tb进行下限推断

它处理返回类型,但不指定任何有关参数类型的内容。我能找到的规范中关于方法组参数类型的唯一相关部分是:

如果E是方法组或隐式类型的匿名函数,而T是委托类型或表达式树类型,则T的所有参数类型都是类型为T的E的输入类型

不幸的是,这无助于修正任何界限

基本上,这是可行的:

使用制度

public class Example
{
    private interface ITest
    {
        int TestFunc();
        int TestFunc2(string value);
    }

    public static void Main()
    {
        ITest t = null;
        DoWork(t.TestFunc);
        DoWork2(t.TestFunc2);
    }

    public static void DoWork<TResult>(Func<TResult> func)
    {
    }

    public static void DoWork2<TResult>(Func<string, TResult> func)
    {
    }
}
公共类示例
{
专用接口测试
{
int TestFunc();
int TestFunc2(字符串值);
}
公共静态void Main()
{
ITest t=null;
道工(t.TestFunc);
DoWork2(t.TestFunc2);
}
公共静态无效工作(Func Func)
{
}
公共静态无效DoWork2(Func Func)
{
}
}

。。。因为在这两种情况下,唯一需要推断的类型参数是返回类型。当您试图根据方法的输入参数推断类型参数时,就会出现问题:(

您能发布调用站点的代码吗?我知道当我传入“(Func)t.TestFunc”时它会工作,但我希望编译器接管这项工作,因为该方法会有不同的变体,而且总是编写类型会很麻烦。@SWeko:callsite是
DoWork(t.TestFunc);
in
Main()
。请注意,问题与接口无关。使用
DoWork(new Test().TestFunc)
也不起作用。Jon Skeet应该知道。他在哪里?