2012-01-28 5 views
5

Я новичок в переполнении стека, поэтому, пожалуйста, успокойся! Я читаю C# в Depth, но я столкнулся с сценарием, который, как я полагаю, не охвачен. Быстрый поиск в Интернете не вызвал никаких результатов.Тип вывода для аргументов типа общих методов

Say я определяю следующие перегруженные методы:

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

void AreEqual(object expected, object actual) 

Если я позвоню AreEqual() без указания типа аргумента:

AreEqual("Hello", "Hello") 

родовой или не общая версия методы вызывается ли? Вызывается ли общий метод с аргументом типа, который выводится, или является не общим методом, вызываемым с аргументами метода, которые неявно отображаются в System.Object?

Надеюсь, мой вопрос ясен. Заранее благодарю за любой совет.

+5

Вы могли бы, конечно, написать простой код, чтобы проверить это ... –

+1

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

+0

@Mitch Wheat - правда, но тогда я бы не стал писать свой первый пост. И это полезно для других, чтобы увидеть ответ здесь. – zekesteer

ответ

5

Генерики могут генерировать функцию AreEqual(string, string). Это более близкое совпадение, чем AreEqual(object, object), поэтому выбирается общая функция.

Интересно, что компилятор выберет эту общую функцию, даже если она приведет к ошибке нарушения ограничения.

Посмотрите на этот пример:

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"); 
     } 
    } 
} 

Даже здесь он будет выбирать общую версию поверх необщего версии. И тогда вы получите эту ошибку:

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'.

Но если добавить функцию Foo(string obj1) он будет работать.

+0

Отличный ответ, спасибо! Хороший пример, я попробовал сам, чтобы просто подтвердить :-) – zekesteer

+0

Обратите внимание, что разрешение перегрузки выполняется компилятором C#, а не .NET framework. – phoog

+0

@phoog - спасибо, я изменил формулировку –