传递方法时,编译器无法确定泛型类型

时间:2011-04-08 09:17:11

标签: c# generics c#-4.0

我在使用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)
    {
    }
}

任何人都可以解释我的问题是什么吗?

2 个答案:

答案 0 :(得分:3)

遗憾的是,类型推断的规则非常复杂。至少,我觉得它们很复杂,而且我相信Eric和Mads还有另外一个简化它们以用于下一版本的规范 - 很可能不会改变实现的内容,而是改变规范中的表达方式。

在这种情况下,基本问题是参数类型的方法组对类型推断没有贡献,即使 return 类型也是如此。特别是,从C#4规范的7.5.2.6开始:

  

否则,如果E是方法组,并且T是具有参数类型T1 ... Tk和返回类型Tb的委托类型或表达式树类型,并且具有类型T1 ... Tk的E的重载分辨率产生具有返回类型的单个方法U,然后从U到Tb进行下限推断。

它处理返回类型,但没有指定任何有关参数类型的内容。我可以找到关于方法组的参数类型的规范的唯一相关位是:

  

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

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

基本上,这是有效的:

使用System;

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

...因为在任何一种情况下唯一需要推断的类型参数是返回类型。当你尝试根据方法的输入参数推断出类型参数时出错了:(

答案 1 :(得分:1)

我假设编译器在这种情况下不会尝试推断类型,因为如果你有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)
    {
    }