2015-10-01 11 views
21

Dlaczego wywoływana jest metoda ogólna, gdy oba przeciążenia byłyby zgodne?Które przeciążenie metody C# jest wybrane?

public static void method1(object obj) 
{ 
    Console.WriteLine("Object"); 
} 

public static void method1<T>(T t) 
{ 
    Console.WriteLine("Type T"); 
} 

public static void Main(String args[]) 
{ 
    method1("xyz"); //Will print "Type T"; 
} 

Nie powinno tu być żadnych konfliktów, prawda?

+0

Podobny do [to pytanie] (http://stackoverflow.com/questions/9017363/ambiguous-method-overloading) – adelphus

Odpowiedz

36

Przeciążenia są rozwiązywane przez wybór najbardziej konkretnego przeciążenia. W tym przypadku method1<string>(string) jest bardziej specyficzny niż method1(object), więc jest to wybrane przeciążenie.

Istnieją szczegóły w section 7.4.2 of the C# specification.

Jeśli chcesz wybrać określone przeciążenie, możesz to zrobić, jawnie przesyłając parametry do żądanych typów. Poniższa wywoła method1(object) przeciążenia zamiast generycznego One:

method1((object)"xyz"); 

Istnieją przypadki, gdzie kompilator nie będzie wiedział, który przeciążeniem, aby wybrać, na przykład:

void method2(string x, object y); 
void method2(object x, string y); 

method2("xyz", "abc"); 

W tym przypadku kompilator nie wie, które przeciążenie wybrać, ponieważ żadne przeciążenie nie jest wyraźnie lepsze od drugiego (nie wie, który ciąg znaków jest niejawnie sprowadzony do obiektu). Tak więc wyemituje błąd kompilatora.

10

C# zawsze wybierze najbardziej szczegółową metodę.

Kompilując

method1("xyz"); 

będzie wyglądać dla wszystkich metod z określoną nazwą, a następnie próbował dopasować parametry. Kompilator będzie wybrać metodę, która jest najbardziej szczegółowe, w tym przypadku byłoby to wolą

method1(string s) 

nad

method1<T>(T t) with T = string 

i wreszcie

method1(object o) 

Uwaga @ doskonałą odpowiedź Erika dla przykład gdzie kompilator nie podejmuje decyzji.

+0

Nie szuka "metody1 (ciąg s)", wygląda na metody z tym samym nazwa następnie określa najlepsze dopasowanie. – juharr

+0

@juharr Masz rację, pozwól mi oczyścić nieco odpowiedź – Vlad274

+0

Nadal musisz usunąć część 'method1 (string s)'.To preferuje 'metodę (Tt)' over 'method1 (obiekt o)' – juharr

2

Ponieważ już przekazujesz T jako parametr, więc nie musisz wpisywać numeru method1<string>("xyz");, możesz po prostu przejść method1("xyz");, .Net już wie, że jest ciągiem znaków. Gdybyś miał metodę1, to byłaby to inna historia.

także od method1(object obj) nie bierze w ciąg jako parametr będzie sprzyjać funkcję rodzajowe pierwszy gdzie można wywnioskować T. Jeśli było zmienić method1(object obj) do method1(string obj) byłoby go faworyzować pierwszy wtedy rodzajową.

+0

Cóż, w rzeczywistości jest to kompilator C#, który implementuje rodzaj ogólny wnioskowanie; p nie ma nic wspólnego z .net –

Powiązane problemy