什么是隐含的泛型类型参数

Ste*_*a D 10 c# generics syntax

所以,我遇到了Servy(/sf/answers/1056876971/)的答案,他的一些代码执行了此操作:

public static int BinarySearch<TSource, TKey>(...)
Run Code Online (Sandbox Code Playgroud)

对于扩展方法,但他称之为:

arr.BinarySearch(...)
Run Code Online (Sandbox Code Playgroud)

我四处询问,有人提到它是一个隐含的泛型类型参数.我用谷歌搜索了他们,但没有找到关于他们的信息.我理解泛型如何工作,但我无法理解如何/何时使用这些.

  1. 为什么servy在他的扩展方法中使用它们?
  2. 我可以搜索一些更正式的名称吗?

Jos*_*hua 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);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

此扩展方法适用于任何 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);
Run Code Online (Sandbox Code Playgroud)

所有四种变体都调用相同的方法并返回相同的结果.类型推断通过查看传递的参数并根据提供的内容自动推断其类型来工作.在上面的示例中,它能够确定类型T是类型,int因为我们传入IEnumerable<int>了参数for IEnumerable<T>.它也能够推断出类型U是类型的,string因为我们传入一个匹配初始类型Twith int和返回字符串的Func .所以Func<T, U>用我们的转换器功能填充Func<int, string>.

从上面的推论中,它是那时的标准通用方法.类型推断和扩展方法只不过是方便/句法糖.事实上,如果你反编译的输出,你可以看到,扩展方法被替换为静态调用和通常与类型参数明确填写定义.(这取决于您的反编译器和设置选项).


Ree*_*sey 6

  1. 在这种情况下,他使用泛型方法,因为它允许他的方法使用a 中包含的任何类型Collection<T>.通用方法使其非常灵活,可用于任何类型.他在调用方法时使用类型推理,因为它简化了调用站点的代码.

  2. 自动处理称为类型干扰,详细介绍了C#语言规范第7.5.2节:类型干扰.如果您想详细了解它,我建议您下载C#语言规范.