所以,我遇到了Servy(https://stackoverflow.com/a/15098242/496680)的答案,他的一些代码就这样做了:
public static int BinarySearch<TSource, TKey>(...)
对于扩展方法,但他称之为:
arr.BinarySearch(...)
我四处询问,有人提到它是一个隐含的泛型类型参数。 我用谷歌搜索了他们,但没有找到关于他们的信息。 我理解泛型如何工作,但我无法理解如何/何时使用这些。
答案 0 :(得分:10)
嗯,你遗漏了最重要的部分,使它全部工作。类型参数可以通过传入的实际对象参数来推断。
例如:
static class Extensions {
internal static IEnumerable<U> Test<T, U>(
this IEnumerable<T> items,
Func<T, U> converter) {
foreach (T item in items) {
yield return converter(item);
}
}
}
此扩展方法适用于任何 IEnumerable类,并会根据您提供的转换器将枚举中的每个项目转换为其他类型。这是标准的泛型。
现在,有很多方法可以调用此方法:
IEnumerable<int> values = Enumerable.Range<int>(1, 10);
Func<int, string> converter = i => i.ToString("0.00");
// Variation 1, explicit calling
IEnumerable<string> results1 = Extensions.Test<int, string>(values, converter);
// Variation 2, explicit calling with type inference
IEnumerable<string> results2 = Extensions.Test(values, converter);
// Variation 3, extension method calling, still providing explicit types
IEnumerable<string> results3 = values.Test<int, string>(converter);
// Variation 4, extension method with type inference
IEnumerable<string> results4 = values.Test(converter);
所有四种变体都调用相同的方法并返回相同的结果。类型推断通过查看传递的参数并根据提供的内容自动推断其类型来工作。在上面的示例中,我们可以确定T
类型的类型为int
,因为我们将IEnumerable<int>
传入IEnumerable<T>
的参数。它还能够推断类型U
的类型为string
,因为我们传入的Func匹配初始类型T
和int
并返回一个字符串。因此Func<T, U>
填充了Func<int, string>
的转换函数。
从上面的推论中,它是那时的标准通用方法。类型推断和扩展方法只不过是方便/句法糖。实际上,如果您对输出进行反编译,您可以看到扩展方法被静态调用替换,并且通常使用显式填充的类型参数进行定义。 (这取决于您的反编译器和设置选项)。
答案 1 :(得分:6)
在这种情况下,他使用generic method因为它允许他的方法使用Collection<T>
中包含的任何类型。通用方法使其非常灵活,可用于任何类型。他在调用方法时使用类型推理,因为它简化了调用站点的代码。
自动处理称为类型干扰,详细介绍了C#语言规范第7.5.2节:类型干扰。如果您想详细了解它,我建议您下载C# language specification。
答案 2 :(得分:2)
我通常听到的术语是“类型推断”。