Подтвердить что ты не робот

С# Общий метод без указания типа

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

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

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

Как этот код может скомпилировать, не указав общий тип? Вызывает ли С# тип во время выполнения?

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

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

Ответ 3

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

Это большая часть того, что делает 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);