2013-05-15 12 views
5

Poniższy kod rzuca "niejednoznaczne wywołania mecz" w czasie kompilacji:Niejednoznaczne wywołanie zamieszania

class ABC{} 
class DEF{} 
class Program 
{ 
    static void Main(string[] args) 
    { 
     Debug.WriteLine(func(null)); 
    } 
    static string func(ABC abc) 
    { 
     return ""; 
    } 
    static string func(DEF def) 
    { 
     return ""; 
    } 
} 

Ale następujący kod kompiluje i działa poprawnie:

static void Main(string[] args) 
{ 
    Debug.WriteLine(func(null)); 
} 
static string func(int? abc) 
{ 
    return "function a"; 
} 
static string func(float? def) 
{ 
    return "function b"; 
} 

Wyprowadzanie

function a 

W jaki sposób C# wie, jaką funkcję wybrać w drugim przykładzie?

Odpowiedz

12

Gdy kompilator wykonuje funkcję przeciążenia na takim wywołaniu funkcji, wybiera jeden z elementów o lepszej funkcji wśród kandydatów, jeśli taki istnieje. Definicja lepiej członka funkcji obejmuje ten fragment w §7.5.3.2 w specyfikacji języka C#:

7.5.3.2 Lepsze członkiem funkcja

[...]

Biorąc pod uwagę argument lista A z zestawem wyrażeń argumentów {E1, E2, ..., EN} i dwoma odpowiednimi elementami funkcyjnymi MP i MQ o parametrach typów {P1, P2, ..., PN} i {Q1, Q2,. .., QN}, MP jest zdefiniowany jako lepszy element funkcji niż MQ, jeśli

  • dla każdego argumentu ukryte konwersji z EX do QX jest nie lepsze niż utajonego przejścia z EX PX i
  • co najmniej jednego argumentu konwersji z EX do PX lepiej niż konwersja z EX na QX.

[...]

W tym przypadku MP to pierwsza metoda (P1 jest int?) i MQ jest drugi sposób (Q1 jest float?). Tak więc zachowanie można łatwo wytłumaczyć, jeśli możemy udowodnić, że konwersja z null do int? jest lepiej niż konwersja na float?.

ta jest określona przez przepisy w §7.5.3.5:

7.5.3.5 Lepiej cel konwersji

Biorąc pod uwagę dwa różne typy T1 i T2, T1 jest lepszy cel konwersji niż T2, jeżeli co najmniej jeden z poniższych warunków:

  • niejawna konwersja od T1 do T2 istnieje i ma bezpośredniej konwersji z T2 T1 istnieje

Ponieważ konwersja niejawna z int do float istnieje tylko jeden z float do int nie (reference), int jest lepszym celem konwersji przy wyborze pomiędzy tymi dwoma typami.

W przykładzie mamy do czynienia z pustych wersjach tych typów, ale ta sama logika ma zastosowanie z powodu

6.1.4 niejawne konwersje dopuszczające wartość null

predefiniowane niejawne konwersje, które działają na nie pustych wartości typów można również używać z formami zerowymi tych typów.

+0

' pływak f = 1; // działa int i = 1.0f; // nie robi praca ' Ok to ma sens – Isaac

+0

ładnie wyjaśnione. –