没有指定类型的C#通用方法

好的,所以我是一个开始使用C#的Java人员,我正在编写并开始制作一个通用的方法,我编写的运行和编译,但它违背我所知道的关于generics应该如何工作的一切,所以我希望有人可以解释这个对我来说:

所以我有一个定义如下的generics方法:

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

但对我来说奇怪的是,我可以调用这个generics方法而无需指定T并且它可以工作:

 List strings = new List() { "a", "b", "c"}; List ints = new List() { 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); } 

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

不,它是在编译时推断的 – 使用了您提供的IEnumerable的generics类型参数,这在编译时是已知的。 通常,在编译时指定与generics和类型参数有关的所有内容 。 如果存在任何类型的不匹配,编译器抱怨并且您的代码将无法编译。

有一些边缘情况需要明确指定类型,这些仅在极少数情况下使用重载方法,有时会出现多种类型参数组合。

与Java相比,C#具有更多的编译时和运行时类型推断function。 如果此主题感兴趣,请参阅我关于此主题的文章:

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

如果您对generics方法类型推断特别感兴趣并且您有半小时的空闲时间,那么我在这里解释我们如何更改C#3中的类型推断算法:

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

C#编译器通常可以在编译时推断generics类型。 当它可以执行此操作时,您不需要指定generics方法的类型。

这是使LINQ“可用”的主要部分。 如果没有编译时类型推断,查询将如下所示:

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

而不是写:

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