Какие правила применяются для выбора одного из двух его общих методов?
Правила в спецификации, которые, к сожалению, чрезвычайно сложны.В ECMA C # 5 стандарте соответствующий бит начинается в разделе 12.6.4.3 («лучший функциональный элемент»).
Однако в этом случае это относительно просто,Оба метода применимы , причем вывод типа происходит отдельно для каждого метода:
- Для метода 1
TEnum
подразумевается как List<MyEnum>
- ДляМетод 2,
TEnum
выводится как MyEnum
Затем компилятор начинает проверять преобразования из аргументов в параметры, чтобы увидеть, является ли одно преобразование "лучше", чем другое.Это рассматривается в разделе 12.6.4.4 («лучшее преобразование из выражения»).
На данный момент мы рассматриваем следующие преобразования:
- Перегрузка 1:
List<MyEnum>
в List<MyEnum>
(поскольку TEnum
определяется как List<MyEnum>
) - Перегрузка 2:
List<MyEnum>
до IEnumerable<MyEnum>
(поскольку TEnum
подразумевается как MyEnum
)
К счастью, здесь помогает первое правило:
При неявном преобразовании C1, которое преобразуется из выражения E в тип T1, и неявном преобразовании C2, которое преобразуется из выражения E втип T2, C1 лучше, чем C2, если выполняется хотя бы одно из следующих условий:
- E имеет тип S и существует преобразование идентификаторов из S в T1, но не из S в T2
Там - это преобразование идентичности из List<MyEnum>
в List<MyEnum>
, но не преобразование удостоверения из List<MyEnum>
в IEnumerable<MyEnum>
, поэтому первое преобразование лучше.
Других преобразований рассматривать не следует, поэтому overload 1 считается лучшим членом функции.
Ваш аргумент о «более общих» и «более конкретных» параметрах был бы действительным, если бы эта более ранняя фаза закончилась в тай-брейке, но это не так:«лучшее преобразование» аргументов в параметры рассматривается раньше, чем «более конкретные параметры».
В общем, разрешение обеих перегрузок невероятно сложно.Он должен учитывать наследование, универсальные параметры, аргументы без типа (например, нулевой литерал, литерал по умолчанию, анонимные функции), массивы параметров, все возможные преобразования.Практически каждый раз, когда в C # добавляется новая функция, она влияет на разрешение перегрузки: (