C # универсальный метод без указания типа - PullRequest
16 голосов
/ 12 февраля 2011

Хорошо, так что я парень из Java, начинающий использовать C #, и я программировал и начал делать универсальный метод, и то, что я написал, работает и компилируется, но это противоречит всему, что я знаю о том, как должны работать дженерики, поэтому я надеюсь, что кто-томожет объяснить это мне:

Итак, у меня есть универсальный метод, определенный следующим образом:

public static List<T> CopyAsList<T>(IEnumerable<T> list, Object lockObject)  
{  
    if (list != null)  
    {  
        lock (lockObject)  
        {  
            return new List<T>(list);  
        }  
    }  
    return null;  
}  

Но странная вещь для меня заключается в том, что я могу вызвать этот универсальный метод, даже не указав T и это будет работать:

List<String> strings = new List<string>() { "a", "b", "c"};
List<int> ints = new List<int>() { 1,2,3};
object lockObject = new object();

foreach (string s in CopyAsList(strings, lockObject))
{
    Console.WriteLine(s);
}

foreach (int i in CopyAsList(ints, lockObject))
{
    Console.WriteLine(i);
}

Как код может компилироваться без указания универсального типа?Выводит ли C # тип во время выполнения?

Ответы [ 3 ]

35 голосов
/ 12 февраля 2011

Нет, это выводится во время компиляции - используется параметр универсального типа в предоставленном вами IEnumerable<T>, который известен во время компиляции. Вообще говоря, все относительно обобщений и параметров типа указывается во время компиляции. Если есть какое-либо несоответствие, компилятор будет жаловаться, и ваш код не будет компилироваться.

В некоторых случаях необходимо явно указывать типы, это происходит только в редких случаях с перегруженными методами, иногда с несколькими комбинациями параметров типа.

13 голосов
/ 12 февраля 2011

C # имеет гораздо больше возможностей вывода типов во время компиляции и во время выполнения, чем Java. Если эта тема вас интересует, посмотрите мои статьи на эту тему:

http://blogs.msdn.com/b/ericlippert/archive/tags/type+inference/

Если вас особенно интересует вывод типа обобщенного метода и у вас есть полчаса, чтобы сэкономить, я объясню, как мы изменили алгоритм вывода типа в C # 3:

http://blogs.msdn.com/b/ericlippert/archive/2006/11/17/a-face-made-for-email-part-three.aspx

11 голосов
/ 12 февраля 2011

Компилятор C # часто может определить обобщенный тип во время компиляции . Если это возможно, вам не нужно указывать тип для универсального метода.

Это основная часть того, что делает LINQ «пригодным для использования». Без вывода типа времени компиляции запросы будут выглядеть так:

IEnumerable<int> myIds = myCollection
                             .Where<MyType>(i => i.Name == "Foo")
                             .Select<MyType, int>(i => i.Id);

Вместо возможности написать:

var myIds = myCollection.Where(i => i.Name == "Foo").Select(i => i.Id);
...