我在使用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)
{
}
}
任何人都可以解释我的问题是什么吗?
答案 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)
{
}