泛型类型推断



我对泛型很满意,但作为一个喜欢了解每个细节的人,我有这个问题。在我的 Where LINQ 扩展方法的实现中

    public static class Extensions
    {
        public static IEnumerable<T> Where<T>(
                         this IEnumerable<T> source, Func<T, bool> predicate)
        {
            foreach (T element in source)
                if (predicate(element))
                    yield return element;
        }
    }

为什么Where<T> T是必要的?为什么不能从IEnumerable<T> T推断出类型?换句话说,为什么签名不能

public static IEnumerable<T> Where(this IEnumerable<T> source, Func<T, bool> predicate)

感谢您的任何帮助。

public static IEnumerable<T> Where(this IEnumerable<T> source, Func<T, bool> predicate)

有了这样的签名,T将是一个未声明的标识符。如果T未在任何地方定义,则不能只使用IEnumerable<T>。因此,您需要在方法级别(或类(级别T泛型参数,以使IEnumerable<T>有意义。

完全

没有理由认为IEnumerable<T>Where<T>中的T必须是一回事;您是说它们必须通过将它们都指定为T

IEnumerable<T>是该方法返回的内容。 Where<T>用于定义用作参数的泛型类型是什么。可以想象,如果您没有将它们都指定为T,则这些T可能是不同的类型。

也就是说:返回类型(IEnumerable<T>(不一定与参数的类型(Where<T>中的T(相关。

参数列表前面的<T>有点像"变量声明" - 就像你不能只说:

x = 10;

您需要先声明该变量:

int x = 10;

只是在这里它是一个Type的变量声明。

现在用法,这完全是另一回事 - 编译器会根据用法和现有签名,尝试推断出每个Type变量中要粘贴哪些"值",但这些签名仍然必须声明。

您正在混合Where<T>方法的定义和它的用法

定义(和声明(函数时,需要 type 参数来向编译器显示该方法是泛型的。将类型参数声明为 T 后,可以使用它来显示输入和输出参数的类型(在本例中为 IEnumerable<T> (。

使用该方法时,您不需要指定它 - 它可以很容易地从第一个输入参数中推断出来。如果您不确定,请尝试以下操作:

var numbers = new List<int> { 1, 2, 3, 4, 5 };
var odds = numbers.Where(x => x % 2 != 0);
// test for example odds is IEnumerable<int> if you want confirmation =)
public static class Foo
{
    public static T Bar<T>(T input) { return input; }
}

通常会推断出类型。

Foo.Bar("test");

但是在这种情况下会发生什么?

Foo.Bar(null); //error

无法推断类型参数,如果这是在编译时,则会出现编译错误。

Foo.Bar<string>(null); //works

相关内容

  • 没有找到相关文章

最新更新