在没有新约束的情况下创建T的新实例

如果想要创建generics的新实例,则需要定义新约束 ,如下所示:

public T SomeMethod() where T : new() { return new T(); } 

是否可以使用reflection在没有新约束的情况下创建T的实例,如此(包含伪代码):

 public T SomeMethod() { if (T has a default constructor) { return a new instance of T; } else { return Factory.CreateNew(); } } 

为此使用Activator.CreateInstance() 。 有关如何使用此方法的详细信息,请参阅http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx 。 基本上,你做的是:

 var obj = (T)Activator.CreateInstance(typeof(T)); 

您可以使用GetConstructors()方法validation它是否具有默认构造函数:

 var constructors = typeof(T).GetConstructors(); 

如果找到参数为零的构造函数,则可以使用Activator.CreateInstance方法。 否则,您使用Factory.CreateNew()方法。

编辑:

要直接查找是否存在没有任何参数的构造函数,可以使用以下检查:

 if (typeof(T).GetConstructor(Type.EmptyTypes) != null) { // ... 

具有where T : new()约束的通用方法通过调用Activator.CreateInstance()实现new T()调用。 这个方法的一个有趣的事情是它不包含约束 ,所以如果你很乐意将检查推迟到运行时,只需使用:

 public T SomeMethod() { return Activator.CreateInstance(); } 

这将完成return new T()所做的事情,或者将引发一个有意义的exception。 因为它处理成功和失败的情况,所以进行任何额外检查没有任何实际好处,除非你想做一些模糊的事情,比如根本不使用构造函数 (可以这样做)。

Marc Gravell答案的最后一句话(强调我的)

…除非你想做一些模糊的事情,比如根本不使用构造函数( 可以这样做

从他对此的评论中,有另一种方法可以实现同样的目的。 我不太清楚哪种表现更好 ,但老实说,我不在乎。 如果您想知道,请点击该链接。 作者展示了一种混合方式。

使用System.Runtime.Serialization.FormatterServices.GetUninitializedObject() (旧的MSDN文档链接 )。

 public static T SomeMethod() { if (typeof(T) == typeof(string)) { return default(T); } return (T)FormatterServices.GetUninitializedObject(typeof(T)); } 

请注意string的特殊注意。 没有它, GetUninitializedObject()将失败。 这是来自MSDN在字符串上使用此方法:

它不会创建未初始化的字符串,因为创建不可变类型的空实例没有任何意义。

它没有说明它失败的原因,而是更多关于为什么会失败的原因。 在此之后,还有另一个注释如下:

您不能使用GetUninitializedObject方法来创建派生自ContextBoundObject类的类型的实例。