【问题标题】:What are implied generic type parameters什么是隐含的泛型类型参数
【发布时间】:2013-02-26 21:37:36
【问题描述】:

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

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

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

arr.BinarySearch(...)

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

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

【问题讨论】:

  • 我可以简单地回答#1。它允许该方法适用于任何类型的集合,而不是仅适用于字符串或整数或 Foos 或其他任何东西。它还允许您与任何类型的值进行比较,可以是 int 或 string 或 Bar 或 [...]。在您的特定情况下,您只需要从某种类型的数组中选择一个int(我什至不知道您的名字)。使用泛型它不仅适用于您的一种情况,而且适用于具有相同问题但类型不同的任何类似情况。这将更有利于未来的访问者找到您的问题。
  • @Servy 谢谢!对于未来的读者,我还发现了这篇文章:stackoverflow.com/questions/4885027/…

标签: c# generics syntax


【解决方案1】:

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

例如:

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&lt;int&gt; 传递到 IEnumerable&lt;T&gt; 的参数中。它还能够推断出U 类型是string 类型,因为我们传入了一个匹配T 的初始类型与int 的Func 并返回一个字符串。所以Func&lt;T, U&gt;被我们的转换器函数Func&lt;int, string&gt;填充。

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

【讨论】:

  • 对于最后两个示例,您需要省略 values 作为参数。
  • 糟糕,谢谢!当你无法编译时,你会错过什么,真是太神奇了!
【解决方案2】:
  1. 在这种情况下,他使用generic method,因为它允许他的方法使用Collection&lt;T&gt; 中包含的任何类型。泛型方法使其非常灵活,可用于任何类型。他在调用方法时使用了类型推断,因为它简化了调用站点的代码。

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 是的,它被称为“类型推断”。 Generic Methods (C# Programming Guide) 有一个完全基本的示例,它说:您也可以省略类型参数,编译器将推断它。以下对 Swap 的调用等同于前面的调用: [...] 类型推断的相同规则适用于静态方法和实例方法。编译器可以根据你传入的方法参数来推断类型参数;它不能仅从约束或返回值推断类型参数。 [...]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-28
    • 1970-01-01
    • 1970-01-01
    • 2012-04-19
    • 2010-09-07
    • 1970-01-01
    相关资源
    最近更新 更多