2012-01-28 15 views
5

Jestem nowicjuszem w Stack Overflow, więc proszę, nie krępuj się! Czytam C# in Depth, ale natknąłem się na scenariusz, w który nie wierzę. Szybkie wyszukiwanie w Internecie nie zwróci również żadnych wyników.Typ wnioskowania dla argumentów typu metod ogólnych

Say I zdefiniować następujące przeciążone metody:

void AreEqual<T>(T expected, T actual) 

void AreEqual(object expected, object actual) 

Jeśli zadzwonię AreEqual() bez określenia typu argumentu:

AreEqual("Hello", "Hello") 

to ogólna lub nierodzajową wersja metody wywoływane? Czy metoda ogólna jest wywoływana z wywnioskowanym argumentem typu, czy też nie jest generyczna metoda wywoływana z argumentami metody, które są niejawnie rzutowane na System.Object?

Mam nadzieję, że moje pytanie jest jasne. Z góry dziękuję za radę.

+5

można oczywiście napisać prosty kod, aby to sprawdzić ... –

+1

http://blogs.msdn.com/b/ericlippert/archive/2009/07/30/generics-are-not-templates.aspx –

+0

@Mitch Wheat - prawda, ale wtedy nie musiałbym robić pierwszego postu. I przydatne dla innych, aby zobaczyć odpowiedź tutaj. – zekesteer

Odpowiedz

5

Generyczne generują funkcję AreEqual(string, string). Jest to bliżej niż AreEqual(object, object), dlatego wybrana jest funkcja ogólna.

Co ciekawe, kompilator wybierze tę funkcję ogólną, nawet jeśli spowoduje to błąd naruszenia ograniczenia.

Spójrz na ten przykład:

using System.Diagnostics; 

namespace ConsoleSandbox 
{ 
    interface IBar 
    { 
    } 

    class Program 
    { 
     static void Foo<T>(T obj1) where T: IBar 
     { 
      Trace.WriteLine("Inside Foo<T>"); 
     } 


     static void Foo(object obj) 
     { 
      Trace.WriteLine("Inside Foo Object"); 
     } 

     static void Main(string[] args) 
     { 

      Foo("Hello"); 
     } 
    } 
} 

nawet tu będzie wybrać generycznej wersji nad wersji non-rodzajowego. A następnie pojawi się ten błąd:

The type 'string' cannot be used as type parameter 'T' in the generic type or method 'ConsoleSandbox.Program.Foo(T)'. There is no implicit reference conversion from 'string' to 'ConsoleSandbox.IBar'.

Ale jeśli dodać funkcję Foo(string obj1) będzie działać.

+0

Świetna odpowiedź, dzięki! Dobry przykład, próbowałem go samodzielnie, aby potwierdzić :-) – zekesteer

+0

Należy zauważyć, że rozdzielczość przeciążania jest wykonywana przez kompilator C#, a nie framework .NET. – phoog

+0

@phoog - dziękuję, zmieniłem sformułowanie –

Powiązane problemy