17

好的,所以我是一个开始使用 C# 的 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);
}

代码是如何在不指定泛型类型的情况下编译的?C# 是否在运行时推断类型?

4

2 回答 2

35

不,它是在编译时推断出来的——使用IEnumerable<T>您提供的泛型类型参数,这在编译时是已知的。一般来说,关于泛型和类型参数的一切都是在编译时指定的。如果存在任何类型的不匹配,编译器抱怨并且您的代码将无法编译。

在某些极端情况下,您必须显式指定类型,这些仅在极少数情况下使用重载方法发生,有时使用类型参数的多种组合。

于 2011-02-12T00:19:37.730 回答
12

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);
于 2011-02-12T00:20:05.473 回答