Смущен из-за разрешения перегрузки метода расширения C# - PullRequest
0 голосов
/ 27 апреля 2020

Рассмотрим следующий код:

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 включено, поэтому оно должно быть в пуле допустимых перегрузок. Фактически, если я удаляю свое расширение, вызывается правильная функция структуры.

Для справки

Редактировать: перемещение их в разные пространства имен показывает ту же проблему:

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

Для справки

Ответы [ 2 ]

2 голосов
/ 27 апреля 2020

Потому что, как говорит Эри c Липперт:

фундаментальное правило, согласно которому одна потенциальная перегрузка оценивается как лучшая, чем другая, для данного места вызова: ближе всегда лучше, чем дальше .

Ближе, лучше

0 голосов
/ 27 апреля 2020

Попробуйте System.Linq.Enumerable.Take(source, 5) вместо Take(source, 5), чтобы принудительно использовать оригинальную функцию "Take" или переименуйте свой собственный "Take" в нечто другое, например "Takef", чтобы избежать подобных проблем.

...