简体   繁体   English

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

[英]Confused about C#'s extension method overload resolution

Consider the following code:考虑以下代码:

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 + " ");
    }
}

I have an extension on IEnumerable<T> for Take(long) , which isn't provided by the framework.我在IEnumerable<T>上有一个Take(long)的扩展,框架没有提供。 The framework only provides Take(int) .该框架仅提供Take(int) And since I'm calling it with an int parameter ( Take(5) ), I would have expected it to use the framework version, but it's calling my extension.而且由于我使用int参数( Take(5) )调用它,我本来希望它使用框架版本,但它正在调用我的扩展。

Am I missing something?我错过了什么吗? The closest match would obviously be the one that takes int as a parameter, and System.Linq is included so it should be in the pool of valid overloads.最接近的匹配显然是将int作为参数的匹配,并且System.Linq包含在内,因此它应该在有效重载池中。 In fact if I delete my extension, the correct framework function is called.事实上,如果我删除我的扩展,就会调用正确的框架 function。

For reference 以供参考

Edit: Moving them to different namespaces shows the same problem:编辑:将它们移动到不同的名称空间显示相同的问题:

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 以供参考

Because as Eric Lippert puts it:因为正如 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越近越好

Try System.Linq.Enumerable.Take(source, 5) instead of just Take(source, 5) to force using the original "Take" function or rename your own "Take" into somthing else "Takef" for example to avoid this kind of problems.尝试System.Linq.Enumerable.Take(source, 5)而不是Take(source, 5)强制使用原始的“Take” function 或将您自己的“Take”重命名为其他“Takef”,例如以避免这种情况的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM