C# 为什么带约束的泛型扩展方法不被认为是扩展方法?

C# 为什么带约束的泛型扩展方法不被认为是扩展方法?,c#,generics,extension-methods,constraints,C#,Generics,Extension Methods,Constraints,可能重复: 考虑两种方法: public static IEnumerable<V> Merge<V> (this IEnumerable<IEnumerable<V>> coll) public static IEnumerable<V> Merge<T, V> (this IEnumerable<T> coll) where T : IEnumer

可能重复:

考虑两种方法:

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>
公共静态IEnumerable合并
(此IEnumerable coll)
公共静态IEnumerable合并
(此IEnumerable coll)
其中T:IEnumerable
这两种方法都可以很好地编译,在这两种情况下,泛型类型的类型在调用程序的编译时都是已知的,因此扩展类型的确切类型也是已知的

两个都可以,但只有第一个可以作为分机

为什么?

更新1 要看到它失败,请使用第二种方法和以下示例:

    var x = new List<List<int>>();
    var y = x.Merge();
var x=新列表();
变量y=x.Merge();
更新--关闭
你们不觉得原来的帖子太复杂了,弄不清楚吗?出于教育目的,我认为这篇文章不应该被关闭,即使在技术上(即答案)它是重复的。只有我的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>();
//IEnumerable定义。。。
列表x=。。。;
//调用第一个方法(隐式)
x、 合并();
//还(显式)调用第一个方法
x、 合并();
//调用第二个方法(显式)
x、 合并();
这三个参数都编译成功了,我只是觉得有了两个泛型类型参数,它无法从用法中推断出第二个泛型类型参数,因此它不会在intellisense中显示,但仍然是合法的


更新:根据询问者的说法,并不是这两个方法被声明为重载,而是它们或者是。鉴于这个原因,Merge()在第二种形式上不起作用,因为t和V之间的关系是在类型约束中定义的,因此不用于Eric在其S.O.回答中所述的类型推理。

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

昨天也提出了同样的问题。更多细节请参见我的答案


我指的是编译器,不是智能感知。对我来说,编写第一个方法并使用它,然后用这个方法交换第二个方法就足够了。在第一种情况下,代码编译正常,在第二种情况下,代码编译不正常。顺便说一句,您忘记了第四种情况——第二种情况是x.Merge()。它也应该(我希望…)编译。@macias:你能举一个不能编译的调用的例子吗?当你说它不能编译时,你是说它不能进行推理吗?还是没有?我用简短的例子更新了问题。要么我遗漏了什么,要么你的简短回答在这里是不够的“从参数和形式参数中进行推断”。应该可以(第二种情况)得到参数的类型,它是T,它可以是(像James的例子)列表。所以我们知道,扩展应该有效。还是不应该?;-)我需要时间让它沉入…@macias:你拥有的事实是(1)T是列表,而(2)T被限制为可数。我们不从约束条件中扣除。所以事实(2)从未被考虑过,所以我们没有任何东西可以从中推断V。啊,现在我明白了。如果您仍在阅读我的评论,请澄清您的博客条目,您指的是模板参数,而不是方法参数。我不知道为什么,但当阅读你们的答案和博客,看到“论点”时,我总是把它和方法论点联系起来,而不是模板论点(我应该这样做)。现在它是完美的清晰!谢谢。@macias:不客气!我同意,这个术语令人困惑。我们有“参数”和“形式参数”,然后是类似的“类型参数”和“类型参数”。当你指的是另一个术语时,很容易不经意地使用一个术语,这可能会让人很困惑。啊,我明白了,所以当你说使用第二种方法时,你指的是第二种方法本身。并不是说这两者都是彼此的重载。。。对吧?在这种情况下,埃里克给你的答案才是真正的原因。因为T和V之间的关系是在约束中指定的,并且编译器不会从约束中推断类型,所以编译器不知道如何解析泛型类型参数V,这就是为什么必须显式指定类型参数V的原因。@James Michael Hare,不知怎的,我错过了必须解析模板参数的部分,不仅仅是方法;-)现在很容易理解编译器(不过,若约束可以是方法定义的一部分,那个么它会有所帮助)。