当传递一个方法时,编译器不能找出泛型类型

本文关键字:编译器 不能 泛型类型 方法 一个 | 更新日期: 2023-09-27 17:49:33

我在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)
    {
    }
}
谁能给我解释一下是什么问题?

当传递一个方法时,编译器不能找出泛型类型

不幸的是,类型推断的规则非常复杂。至少,我发现它们很复杂,我相信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)
    {
    }
}

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

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