Czy to błąd?
Tak.
Gratulacje, znalazłeś błąd w rozwiązaniu problemu z przeciążeniem. Błąd odtwarza się w C # 4 i 5; nie odtwarza się w wersji „Roslyn” analizatora semantycznego. Poinformowałem zespół testowy C # 5 i mam nadzieję, że uda nam się to zbadać i rozwiązać przed ostatecznym wydaniem. (Jak zawsze, żadnych obietnic.)
Następuje prawidłowa analiza. Kandydaci to:
0: C(params string[]) in its normal form
1: C(params string[]) in its expanded form
2: C<string>(string)
3: C(string, object)
Kandydat zerowy oczywiście nie string
ma zastosowania, ponieważ nie można go zamienić na string[]
. To pozostawia trzy.
Z tych trzech musimy określić jedyną najlepszą metodę. Robimy to, dokonując porównań parami trzech pozostałych kandydatów. Są trzy takie pary. Wszystkie z nich mają identyczne listy parametrów po usunięciu pominiętych parametrów opcjonalnych, co oznacza, że musimy przejść do zaawansowanej rundy rozstrzygającej, opisanej w sekcji 7.5.3.2 specyfikacji.
Co jest lepsze, 1 czy 2? Istotną kwestią rozstrzygającą jest to, że metoda ogólna jest zawsze gorsza niż metoda nieogólna. 2 jest gorsze niż 1. Zatem 2 nie może być zwycięzcą.
Co jest lepsze, 1 czy 3? Istotna rozstrzygająca kwestia to: metoda stosowana tylko w rozszerzonej formie jest zawsze gorsza niż metoda stosowana w jej normalnej formie. Zatem 1 jest gorszy niż 3. Zatem 1 nie może być zwycięzcą.
Co jest lepsze, 2 czy 3? Istotną kwestią rozstrzygającą jest to, że metoda ogólna jest zawsze gorsza niż metoda nieogólna. 2 jest gorsze niż 3. Zatem 2 nie może być zwycięzcą.
Aby zostać wybranym spośród wielu odpowiednich kandydatów, kandydat musi (1) być niepokonany, (2) pokonać co najmniej jednego innego kandydata oraz (3) być jedynym kandydatem, który ma dwie pierwsze właściwości. Kandydat trzeci nie został pokonany przez żadnego innego kandydata i pokonuje co najmniej jednego innego kandydata; jest to jedyny kandydat z tą własnością. Dlatego kandydat trzeci jest jedynym najlepszym kandydatem . Powinien wygrać.
Kompilator C # 4 nie tylko popełnia błąd, jak słusznie zauważyłeś, zgłasza dziwny komunikat o błędzie. To, że kompilator źle analizuje rozdzielczość przeciążenia, jest nieco zaskakujące. To, że wyświetla nieprawidłowy komunikat o błędzie, nie jest zaskakujące; heurystyka błędu „niejednoznacznej metody” zasadniczo wybiera dowolne dwie metody ze zbioru kandydatów, jeśli nie można określić najlepszej metody. Niezbyt dobrze jest znaleźć „prawdziwą” dwuznaczność, jeśli w rzeczywistości taka istnieje.
Można rozsądnie zapytać, dlaczego tak jest. Trudno jest znaleźć dwie metody, które są „jednoznacznie niejednoznaczne”, ponieważ relacja „lepszości” jest nieprzechodnia . Można wymyślić sytuacje, w których kandydat 1 jest lepszy od 2, 2 jest lepszy od 3, a 3 jest lepszy od 1. W takich sytuacjach nie możemy zrobić nic lepszego niż wybranie dwóch z nich jako „niejednoznacznych”.
Chciałbym ulepszyć tę heurystykę dla Roslyn, ale ma ona niski priorytet.
(Ćwiczenie do czytelnika: „Opracowanie algorytmu czasu liniowego w celu zidentyfikowania unikalnego najlepszego członka zbioru n elementów, w którym relacja lepszości jest nieprzechodnia” było jednym z pytań, które zadano mi w dniu, w którym przeprowadzałem wywiad dla tego zespołu. bardzo trudny algorytm; daj mu szansę.)
Jednym z powodów, dla których odkładaliśmy dodawanie opcjonalnych argumentów do C # przez tak długi czas, była liczba złożonych niejednoznacznych sytuacji, które wprowadza do algorytmu rozwiązywania przeciążeń; najwyraźniej nie zrobiliśmy tego dobrze.
Jeśli chcesz zgłosić problem dotyczący połączenia, aby go śledzić, nie krępuj się. Jeśli chcesz tylko zwrócić na to naszą uwagę, pomyśl, że to zrobione. W przyszłym roku przejdę do testów.
Dziękuję za zwrócenie mi na to uwagi. Przepraszamy za błąd.
'Overloaded.ComplexOverloadResolution(string)'
odnosi się do<string>(string)
metody; Myślę, że odnosi się to do(string, object)
metody bez dostarczonego obiektu.