C# 泛型类型推断

C# 泛型类型推断,c#,.net,linq,generics,C#,.net,Linq,Generics,我对泛型很满意,但作为一个喜欢理解每一个细节的人,我有这个问题。在我对WhereLINQ扩展方法的实现中 public static class Extensions { public static IEnumerable<T> Where<T>( this IEnumerable<T> source, Func<T, bool> predicate)

我对泛型很满意,但作为一个喜欢理解每一个细节的人,我有这个问题。在我对
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;
        }
    }
谢谢您的帮助。

参数列表前面的
有点像“变量声明”—就像您不能只说:

x = 10;
您需要首先声明该变量:

int x = 10;
这里是
类型的变量声明

现在使用,这是另一回事了-编译器将尽最大努力根据使用情况和现有签名推断出这些
Type
变量中每个变量的“值”,但这些签名仍然必须声明

公共静态IEnumerable其中(此IEnumerable源,Func谓词)


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

没有任何理由认为
IEnumerable
中的
T
其中的
必须是相同的东西;通过将它们都指定为
T

IEnumerable
是该方法返回的内容<代码>其中
用于定义用作参数的泛型类型。如果您没有将它们都指定为
T

也就是说:返回类型(
IEnumerable
)不一定与参数类型相关(其中
中的
T

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

Foo.Bar(null); //error
无法推断类型参数,如果是在编译时,则会出现编译错误

Foo.Bar<string>(null); //works
Foo.Bar(空)//作品
您将
方法的定义和用法混为一谈

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

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

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 =)
var number=新列表{1,2,3,4,5};
var赔率=数字。其中(x=>x%2!=0);
//例如,如果希望确认,则测试赔率为IEnumerable=)

我认为它可以,但在它不能的情况下,它是存在的。在大多数情况下,您可以使用
Where
而不提供
T
。@JonathanWood:他说的是声明签名,而不是调用。无论如何,为了能够提供
T
,它必须在声明中。我错过了什么?@Mark例如,如果您声明
公共类T{}
编译器会做什么?您的方法是否突然变得非泛型,因为在另一个文件中有人声明了名为
T
的类型?@标记否,您的新版本没有声明泛型方法。它是一种普通方法,其形式参数和返回类型为封闭泛型类型(例如,
IEnumerable
,在这种情况下,
T
是实际类型),但方法本身不是泛型的。泛型方法具有一个或多个类型参数,在调用该方法时必须为其指定(或推断)类型参数。将其声明为
,其中
表示这是一个具有单个类型参数的通用方法,该类型将由占位符
T
表示。
Foo.Bar(null); //error
Foo.Bar<string>(null); //works
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 =)