12

所以,我遇到了Servy(https://stackoverflow.com/a/15098242/496680)的答案,他的一些代码是这样做的:

public static int BinarySearch<TSource, TKey>(...)

对于扩展方法,但他这样称呼它:

arr.BinarySearch(...)

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

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

3 回答 3

11

好吧,您遗漏了使一切正常的最重要部分。类型参数可以通过传入的实际对象参数来推断。

例如:

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);

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

从上面的推论来看,这是一个标准的通用方法。类型推断和扩展方法只不过是方便/语法糖。事实上,如果您反编译输出,您可以看到扩展方法被静态调用替换,并且通常使用显式填写的类型参数来定义。(这取决于您的反编译器和设置的选项)。

于 2013-02-26T21:54:45.370 回答
6
  1. 在这种情况下,他使用了一个泛型方法,因为它允许他的方法与包含在Collection<T>. 泛型方法使其非常灵活,可用于任何类型。他在调用方法时使用了类型推断,因为它简化了调用站点的代码。

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

于 2013-02-26T21:43:11.227 回答
2

我经常听到的术语是“类型推断”。

于 2013-02-26T21:39:54.503 回答