Blindy
Blindy

Reputation: 67544

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

Upvotes: 0

Views: 89

Answers (2)

kiliz
kiliz

Reputation: 95

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.

Upvotes: 0

David Browne - Microsoft
David Browne - Microsoft

Reputation: 89424

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

Upvotes: 2

Related Questions