правила разрешения перегрузки c#

предположим следующие методы расширения:

public static string ToFooBarString(this object obj)
{
...
}

public static string ToFooBarString< T >(this IEnumerable< T > obj)
{
...
}

Теперь я вызываю это поверх реализации интерфейса IEnumerable‹ T>, скажем

Dictionary< int , string > f; // implements IEnumerable< KeyValuePair< int , string > >
f.ToFooBarString(); // <--- which one is called?

какой из них называется в данном случае и почему?


person lurscher    schedule 27.04.2012    source источник
comment
Почему бы не попробовать самому?   -  person Daniel Mann    schedule 27.04.2012
comment
@DBM, я бы хотел, но тогда я бы ничему не научился в следующий раз, когда мне нужно будет придумать что-то подобное   -  person lurscher    schedule 27.04.2012


Ответы (2)


Компилятор выбирает перегрузку, «ближайшую» к рассматриваемому типу. Таким образом, он выберет вторую перегрузку. (Когда компилятор не может понять это, он будет жаловаться на неоднозначность.)

Поскольку «объект» находится на вершине иерархии, в первую очередь будет использоваться любая другая применимая перегрузка.

Что еще более важно, это можно обнаружить с помощью тестирования и чтения многочисленных книг, онлайн-статей, документации, блогов и т. д. Небольшое гугление должно было найти это быстрее, чем публикация здесь.

person John Fisher    schedule 27.04.2012
comment
Думаю, я понимаю, что вы имеете в виду, но есть ли строгое значение слова «близость»? - person lurscher; 27.04.2012
comment
Сначала пробует классы, находящиеся ниже всех в иерархии наследования. - person SimpleVar; 27.04.2012
comment
поэтому, если бы я добавил еще одну общую перегрузку, скажем, ICollection< T > (которая также реализована Dictionary, тогда компилятору пришлось бы жаловаться на двусмысленность, верно? - person lurscher; 27.04.2012
comment
@lurscher: Лично я думаю, что было бы гораздо быстрее попробовать, чем спрашивать здесь. - person John Fisher; 27.04.2012
comment
@lurscher: Есть ли строгое значение слова «близость»? Да. Прочитайте спецификацию. В частности, вам нужен раздел, который определяет значение лучшего преобразования из типа. Если вы добавите метод расширения, который принимает ICollection<T>, будет ли это двусмысленно? № ICollection<T> более конкретен, чем object или IEnumerable<T>, и, следовательно, обеспечивает лучшее преобразование из словарного типа. - person Eric Lippert; 27.04.2012

Будет вызван второй метод. Он основан на правилах преобразования типов:

Прочитайте разрешение перегрузки на языке C#. Технические характеристики. В частности, вы можете посмотреть 7.4.2.3, где рассказывается о том, как разрешаются конфликты преобразования.

person John Koerner    schedule 27.04.2012