我对仿制药很满意,但是我喜欢理解我有这个问题的每一个细节。在我的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;
}
}
为什么T
中的Where<T>
是必要的?为什么不能从T
中的IEnumerable<T>
推断出类型?换句话说,为什么签名不能
public static IEnumerable<T> Where(this IEnumerable<T> source, Func<T, bool> predicate)
感谢您的帮助。
答案 0 :(得分:4)
public static IEnumerable<T> Where(this IEnumerable<T> source, Func<T, bool> predicate)
使用这样的签名,T
将是未声明的标识符。如果IEnumerable<T>
未在任何地方定义,则不能只使用T
。因此,您需要在T
的方法(或类)上使用通用参数IEnumerable<T>
才能理解。
答案 1 :(得分:2)
根本没有理由T
和IEnumerable<T>
中的Where<T>
必须是同一个东西;你说他们必须将它们都指定为T
IEnumerable<T>
是该方法返回的内容。 Where<T>
用于定义用作参数的泛型类型。可以想象,如果您没有将T
指定为T
IEnumerable<T>
可能是不同的类型
即:返回类型(T
)不一定与参数类型(Where<T>
中的{{1}})相关。
答案 2 :(得分:1)
参数列表前面的<T>
表现得有点像“变量声明” - 就像你不能只说:
x = 10;
您需要先声明该变量:
int x = 10;
就在这里,它是Type
的变量声明。
现在用法,这完全是另一回事 - 编译器最大限度地尝试根据使用情况推断每个Type
变量中的“值”。现有的签名,但仍然必须声明这些签名。
答案 3 :(得分:1)
您正在混合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 =)
答案 4 :(得分:0)
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