Search code examples
c#overloadingoverload-resolution

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. The framework only provides 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.

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. In fact if I delete my extension, the correct framework function is called.

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


Solution

  • Because as Eric Lippert puts it:

    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