Це помилка?
Так.
Вітаємо, ви знайшли помилку в роздільній здатності перевантаження. Клоп відтворюється в C # 4 і 5; він не відтворюється у "Рослінському" варіанті семантичного аналізатора. Я поінформував тестову команду C # 5, і, сподіваємось, ми зможемо розглянути це питання і вирішити до остаточного випуску. (Як завжди, жодних обіцянок.)
З цього випливає правильний аналіз. Кандидатами є:
0: C(params string[]) in its normal form
1: C(params string[]) in its expanded form
2: C<string>(string)
3: C(string, object)
Нуль кандидата, очевидно, не застосовується, оскільки string
не може бути конвертований string[]
. Це залишає три.
З трьох, ми повинні визначити унікальний найкращий метод. Ми робимо це, порівнюючи порівняння трьох кандидатів. Таких пар є три. Усі вони мають ідентичні списки параметрів, коли ми знімемо пропущені необов'язкові параметри, а це означає, що нам належить перейти до розширеного раунду розв'язування, описаного в розділі 7.5.3.2 специфікації.
Що краще, 1 або 2? Відповідний переломник полягає в тому, що загальний метод завжди гірший, ніж негенеричний метод. 2 гірше 1. Отже, 2 не можуть бути переможцями.
Що краще, 1 або 3? Відповідним розривом є: метод, застосовуваний лише у розгорнутому вигляді, завжди гірший, ніж метод, застосований у його звичайній формі. Тому 1 гірший за 3. Отже, 1 не може бути переможцем.
Що краще, 2 або 3? Відповідний переломник полягає в тому, що загальний метод завжди гірший, ніж негенеричний метод. 2 гірше 3. Отже, 2 не можуть бути переможцями.
Для вибору з безлічі застосованих кандидатів кандидат повинен бути (1) непереможеним, (2) перемогти принаймні одного іншого кандидата і (3) бути єдиним кандидатом, який має перші два властивості. Кандидат трьох не бив жодного іншого кандидата, і б'є принаймні одного іншого кандидата; це єдиний кандидат з цим властивістю. Тому кандидат три - це єдиний найкращий кандидат . Це має виграти.
Мало того, що компілятор C # 4 помиляється, оскільки ви правильно зазначаєте, що він повідомляє про химерне повідомлення про помилку. Те, що компілятор неправильно аналізує роздільну здатність перевантаження, трохи дивно. Те, що це неправильне повідомлення про помилку, зовсім не дивно; евристична помилка "неоднозначного методу" в основному вибирає будь-які два методи з набору кандидатів, якщо кращого методу неможливо визначити. Не дуже добре знаходити "справжню" неоднозначність, якщо насправді вона є.
Можна з розумом запитати, чому це так. Це досить складно знайти два методу , які є «недвозначно неоднозначним» , тому що «betterness» ставлення неперехідне . Можна придумати ситуації, коли кандидат 1 кращий за 2, 2 кращий за 3, а 3 кращий за 1. У таких ситуаціях ми не можемо зробити кращого, ніж вибрати два з них як «неоднозначні».
Я хотів би покращити цю евристику для Росліна, але це низький пріоритет.
(Вправа для читача: "Розробити алгоритм лінійного часу, щоб визначити унікального найкращого члена набору з n елементів, де відношення кращості є неперехідним", було одним із запитань, що мені задавали в той день, коли я брав інтерв'ю для цієї команди. Це не так дуже важкий алгоритм; спробуйте.)
Однією з причин того, чому ми так довго наполягали на додаванні необов'язкових аргументів до C #, була кількість складних неоднозначних ситуацій, які вона вводить в алгоритм вирішення перевантаження; мабуть, ми не зрозуміли це правильно.
Якщо ви хочете ввести проблему Connect, щоб відстежити її, не соромтеся. Якщо ви просто хочете, щоб він був донесений до нас, вважайте це зробленим. Я продовжуватиму тестування наступного року.
Дякую за те, що ви звернули увагу на це Вибачте за помилку.
'Overloaded.ComplexOverloadResolution(string)'
стосується<string>(string)
методу; Я думаю, що це стосується(string, object)
методу, який не надається об'єктом.