对 C# 的扩展方法重载解析感到困惑

Confused about C#'s extension method overload resolution

考虑以下代码:

using System;
using System.Linq;
using System.Collections.Generic;

public static class Ex
{
    public static IEnumerable<T> Take<T>(this IEnumerable<T> source, long cnt)
    {
        return source;
    }
}

public class C 
{
    public static void Main() 
    {
        foreach(var e in Enumerable.Range(0, 10).Take(5).ToArray())
            Console.Write(e + " ");
    }
}

我在 IEnumerable<T> 上有 Take(long) 的扩展,框架没有提供。该框架仅提供Take(int)。由于我使用 int 参数 (Take(5)) 调用它,我希望它使用框架版本,但它调用了我的扩展。

我错过了什么吗?最接近的匹配显然是将 int 作为参数的匹配,并且包含 System.Linq 因此它应该在有效重载池中。事实上,如果我删除我的扩展,就会调用正确的框架函数。

For reference

编辑:将它们移动到不同的命名空间显示相同的问题:

using System;
using System.Linq;
using System.Collections.Generic;

namespace N1
{
    public static class Ex
    {
        public static IEnumerable<T> Take<T>(this IEnumerable<T> source, long cnt)
        {
            return source;
        }
    }
}

namespace N2
{
    using N1;
    public class C 
    {
        public static void Main() 
        {
            foreach(var e in Enumerable.Range(0, 10).Take(5).ToArray())
                Console.Write(e + " ");
        }
    }
}

For reference

尝试 System.Linq.Enumerable.Take(source, 5) 而不是 Take(source, 5) 以强制使用原始 "Take" 函数或将您自己的 "Take" 重命名为其他东西 "Takef" 例如避免此类问题。

因为正如 Eric Lippert 所说:

the fundamental rule by which one potential overload is judged to be better than another for a given call site: closer is always better than farther away.

Closer is better