Разрешение метода говорит, что лучше ближе . См. Сообщение в блоге для точных правил.
Что означает более близкое? Компилятор увидит, может ли он найти точное совпадение, если он не может найти по какой-либо причине, он найдет следующие возможные совместимые методы и т. Д.
Давайте сначала сделаем этот метод компиляцией, удалив ограничение SomeInterface
.
public static class ExtensionMethods
{
public static void Method(this T parameter) //where T : SomeInterface
{ }
public static void Method(this IEnumerable parameter) //where T : SomeInterface
{ }
}
Теперь компилятор с удовольствием компилирует и замечает, что оба вызова метода идут до Method(T)
, а не Method(IEnumerable
. Почему?
Поскольку Method(T)
ближе в том смысле, что может принимать любой тип в качестве параметра, а также не требует никакого преобразования.
Почему
blockquote>Method(IEnumerable
не ближе?) Это потому, что у вас есть тип времени компиляции переменной как
List
, поэтому для него требуется преобразование ссылок отList
доIEnumerable
. Который ближе, но не делает никаких конверсий вообще.Вернемся к вашему вопросу.
Почему
blockquote>instances.Method();
не компилируется?Опять же, как было сказано ранее для использования
Method(IEnumerable
, нам нужно какое-то ссылочное преобразование, так что очевидно, что это не ближе. Теперь у нас остается только один метод, который очень близок) Method
. Но проблема в том, что вы ограничили его с помощьюSomeInterface
, и, очевидно,List
не конвертируется в() SomeInterface
.Проблема (угадывание) проверка общих ограничений происходит после того, как компилятор выбирает более близкую перегрузки. Это делает недействительной выбранную лучшую перегрузку в этом случае.
Вы можете легко исправить это, изменив статический тип переменной на
IEnumerable
, который будет работать, и теперь вы знаете, почему.IEnumerable
instances = new List ();
Первый подход определяет общий словарь, значения которого являются общим списком, что означает, что он может хранить значения любого типа. Это также используется при определении таблиц, так как таблицы могут хранить столбцы с различными типами.
Во втором подходе, когда вы вставляете первое значение в словарь, он устанавливает тип списка значений словаря для этого типа элемента. Так что теперь это простой список.
q) d2: ()!()
q) d2[`t1]:2017.01.01
q) type value d2 / 14h
Это означает, что теперь значения словаря не могут быть общим списком и могут хранить только элементы типа даты.
Чтобы создать общий словарь (в котором хранится общий список в качестве значений), введите значение первой записи как ноль (: :). Это то, что используется словарями пространства имен.
q) d2: ()!()
q) d2[`]:(::)
Теперь он может хранить любое значение.
q) d2[`t2]:2018.01.01
q) d2[`idx]:42
Когда вы определяете словарь как d:()!()
, первое, что вы вставляете (в данном случае, дату), заставит тип словаря принимать только значения типа -14h
. Стандартная практика - инициализировать dict нетипизированным значением, чтобы значение не становилось простым вектором
d2:enlist[`]!enlist(::)
d2[`t1]:2017.01.01
d2[`t2]:2018.01.01
d2[`idx]:42
d2
| ::
t1 | 2017.01.01
t2 | 2018.01.01
idx| 42
.