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

时间:2013-06-26 06:43:48

标签: c# .net generics reflection instantiation

如果想要创建泛型的新实例,则需要定义new constraint,如下所示:

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

3 个答案:

答案 0 :(得分:16)

使用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)
{
    // ...

答案 1 :(得分:10)

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

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

要么完成<{1}} 所做的事情,否则会引发有意义的异常。因为它处理成功和失败的情况,所以进行任何额外检查没有任何实际好处,除非你想做一些模糊的事情,比如根本不使用构造函数(可以这样做)。 / p>

答案 2 :(得分:1)

马克·格雷夫(Marc Gravell)的答案的最后一句话(强调我的意思)

  

...除非您想做一些晦涩的事情,例如不使用构造函数   完全(可以做到

并且在他的this comment中,有另一种方法可以实现相同的目的。我不太知道哪个是better performance wise,但是说实话,我不在乎。如果您想知道,请点击该链接。那里的作者展示了一种 hybrid 方式。

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

public static T SomeMethod<T>()
{
    if (typeof(T) == typeof(string))
    {
        return default(T);
    }

    return (T)FormatterServices.GetUninitializedObject(typeof(T));
}

请注意string的特殊注意事项。否则GetUninitializedObject()将会失败。这是MSDN上在字符串上使用这种方法的结果:

  

它不会创建未初始化的字符串,因为会创建一个空的   不变类型的实例毫无用处。

它没有说明为什么失败,但没有说明为什么应该失败。此后立即有另一个 Note 如下:

  

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