【问题标题】:Why generic extension method with constraint is not recognized as extension method? [duplicate]为什么具有约束的通用扩展方法不被识别为扩展方法? [复制]
【发布时间】:2011-08-24 17:07:44
【问题描述】:

可能重复:
No type inference with generic extension method

考虑两种方法:

public static IEnumerable<V> Merge<V>
       (this IEnumerable<IEnumerable<V>> coll)

public static IEnumerable<V> Merge<T, V>
       (this IEnumerable<T> coll) 
              where T : IEnumerable<V>

两者都编译得很好,在这两种情况下,泛型类型的类型将在调用者的编译时知道,因此扩展类型的确切类型。

你可以同时调用两个,但只能将第一个作为扩展名。

为什么?

更新 1

要失败,请使用第二种方法和这样的例子:

    var x = new List<List<int>>();
    var y = x.Merge();

更新 -- 关闭

你们不觉得原帖太详细了,看不清楚吗?出于教育目的,我认为不应关闭此帖子,即使在技术上(即答案)它是重复的。只是我的 2 美分。

【问题讨论】:

  • 啊,我明白了,所以当你说使用第二种方法时,你说的是第二种方法本身。并不是说这两者都是彼此的重载……对吧?
  • 在这种情况下,Eric 提到的 SO 回答才是真正的原因。因为 T 和 V 之间的关系是在约束中指定的,并且编译器不会从约束中推断类型,所以编译器不知道如何解析你的泛型类型参数 V,这就是为什么你必须显式指定类型参数 V。跨度>
  • @James Michael Hare,不知何故,我错过了必须解决模板参数的部分,而不仅仅是方法;-) 现在编译器很容易理解(但是,如果可以使用约束,它会有所帮助方法定义的一部分)。

标签: c# generics extension-methods constraints


【解决方案1】:

方法类型推断在进行推断时不考虑约束。

昨天也有人问过同样的问题。有关详细信息,请参阅我的答案。

No type inference with generic extension method

【讨论】:

  • 要么我错过了一些东西,要么你的简短回答在这里“从参数和形式参数中扣除”是不够的。应该有可能(第二种情况)获得参数的类型,它是 T,它可以是(如在 James 的示例中)List。所以 T 知道,扩展应该有效。还是不应该? ;-) 我需要时间让它沉入...
  • @macias:您拥有的事实是 (1) T 是 List,并且 (2) T 被限制为 IEnumerable。我们不从约束中扣除。因此,从不考虑事实 (2),因此我们没有任何东西可以从中推断出 V。
  • 啊,现在我明白了。如果您仍在阅读我的评论,请澄清您的博客条目,您的意思是模板参数,而不是方法参数。我不知道为什么,但是在阅读您的答案和博客并看到“参数”时,我经常将其与方法参数相关联,而不是模板参数(我应该这样做)。现在完全清楚了!谢谢。
  • @macias:不客气!我同意,术语令人困惑。我们有“参数”和“形式参数”,然后类似地有“类型参数”和“类型参数”。当你指的是另一个术语时,很容易不小心使用一个术语,并且可能会很混乱。
【解决方案2】:

我认为问题不是不能调用第二个,而是 IntelliSense 不会看到它,因为它无法在没有明确帮助的情况下从您的调用中轻松推断出第二个泛型类型参数 V

例如,给定你的两种扩展方法,以下都是合法的

    // IEnumerable<IEnumerable<int>> definition...
    List<List<int>> x = ...;

    // calls your first method (implicitly)
    x.Merge();

    // also calls your first method (explicitly)
    x.Merge<int>();

    // calls your second method (explicitly)
    x.Merge<List<int>, int>();

所有这三个都编译成功,我只是认为使用两个泛型类型参数,它无法推断您的第二个泛型类型参数从用法中,因此它没有显示在智能感知中,但仍然合法...

更新:根据提问者的说法,这两个方法不是被声明为重载,而是它们是非此即彼。鉴于此原因 Merge() 不适用于第二种形式,因为 T 和 V 之间的关系在类型约束中定义,因此不用于类型推断,如 Eric 在他的 S.O. 中所述。回答。

【讨论】:

  • 我指的是编译器,而不是 IntelliSense。我写第一个方法并使用它就足够了,然后将这个方法换成第二个。在第一种情况下代码编译正常,在第二种情况下 - 不是。顺便提一句。您忘记了第四种情况-第二种情况是 x.Merge() 。它也应该(我希望...)编译。
  • @macias:您能举一个无法编译的调用示例吗?当您说它无法编译时,您是在说推理吗?还是没有?
  • 我用简短的例子更新了问题。
猜你喜欢
  • 1970-01-01
  • 2016-12-24
  • 1970-01-01
  • 2011-04-29
  • 2011-02-05
  • 1970-01-01
  • 1970-01-01
  • 2022-09-30
  • 1970-01-01
相关资源
最近更新 更多