创建一个没有新约束的T的新实例
本文关键字:约束 新实例 实例 一个 创建 新约束 | 更新日期: 2023-09-27 18:20:00
如果想要创建泛型的新实例,则需要定义新约束,如下所示:
public T SomeMethod<T>() where T : new()
{
return new T();
}
有没有可能,使用反射,在没有新约束的情况下创建一个T的实例,比如这样(包含伪代码):
public T SomeMethod<T>()
{
if (T has a default constructor)
{
return a new instance of T;
}
else
{
return Factory<T>.CreateNew();
}
}
为此使用Activator.CreateInstance()
。看见http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx有关如何使用此方法的详细信息。基本上,你所做的是:
var obj = (T)Activator.CreateInstance(typeof(T));
您可以使用GetConstructors()
方法验证它是否有默认构造函数:
var constructors = typeof(T).GetConstructors();
如果找到一个参数为零的构造函数,则可以使用Activator.CreateInstance
方法。否则,使用Factory<T>.CreateNew()
方法。
编辑:
要直接找出是否存在没有任何参数的构造函数,可以使用以下检查:
if (typeof(T).GetConstructor(Type.EmptyTypes) != null)
{
// ...
where T : new()
约束的泛型方法通过调用Activator.CreateInstance<T>()
来实现new T()
调用。这个方法的一个有趣之处在于,它不包括约束,所以如果您愿意将检查推迟到运行时,只需使用:
public T SomeMethod<T>() {
return Activator.CreateInstance<T>();
}
这将执行与return new T()
完全相同的操作,或者将引发有意义的异常。因为它同时处理成功和失败的情况,所以做任何额外的检查都没有真正的好处,除非你想做一些模糊的事情,比如根本不使用构造函数(这是可以做到的)。
Marc Gravell答案的最后一句话(强调我的)
除非你想做一些晦涩难懂的事情,比如不使用构造函数完全(可以这样做)
从他的这句话来看,还有一种实现同样目标的选择。我不知道哪一个表现更好,但老实说,我不在乎。如果你想知道,请点击该链接。作者展示了一种混合的方式。
使用System.Runtime.Serialization.FormatterServices.GetUninitializedObject()
(旧的MSDN文档链接)。
public static T SomeMethod<T>()
{
if (typeof(T) == typeof(string))
{
return default(T);
}
return (T)FormatterServices.GetUninitializedObject(typeof(T));
}
请注意string
的特殊护理。如果没有这个GetUninitializedObject()
就会失败。这是MSDN关于在字符串上使用这种方法的文章:
它不会创建未初始化的字符串,因为创建了一个空字符串不可变类型的实例没有任何作用。
它没有说明失败的原因,而是更多地说明了应该失败的原因。紧接着,还有另一个注释,如下所示:
不能使用GetUninitializedObject方法创建实例派生自ContextBoundObject类的类型的。