获取类型的默认构造函数的最有效方法


73

获取System.Type的默认构造函数(即无参数的实例构造函数)的最有效方法是什么?

我在想下面的代码,但似乎应该有一种更简单有效的方法。

Type type = typeof(FooBar)
BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
type.GetConstructors(flags)
    .Where(constructor => constructor.GetParameters().Length == 0)
    .First();

Answers:


136
type.GetConstructor(Type.EmptyTypes)

6
您从未看过的静态成员...太棒了。
达伦·科普

1
私人成员也不看。假设您只需要公开,那么这似乎是最简单的。但是它最快吗?我正在研究一个测试,以找出答案。
Wes Haggard

7
与我使用MeasureIt(msdn.microsoft.com/en-us/magazine/cc500596.aspx)进行比较后,这种方法在所有情况下(除了最简单的情况)都更快,甚至在那时也几乎不慢。因此,这是最简单也是最快的。谢谢!
Wes Haggard

31

如果您确实需要ConstructorInfo对象,请参见Curt Hagenlocher的答案

另一方面,如果您真的只是想在运行时从创建一个对象System.Type,请参见System.Activator.CreateInstance-它不仅要面向未来(Activator处理的细节比还要多ConstructorInfo.Invoke),而且丑陋得多


3
潜在的危险建议,因为某些对象没有默认的构造函数(字符串为1)。因此,如果只是随意调用此方法,则可能会遇到MissingMethod异常。我实际上必须在调用此方法之前检查默认的构造函数。
cunningdave

正如cunningdave所写,您很可能希望捕获并优雅地处理此方法可能抛出的异常集的至少一部分,这会使调用再次变得不那么美观。另一方面,使用ConstructorInfo的解决方案实际上首先看起来很丑陋,但允许您处理所有这些特殊情况而无需先引发并捕获异常,这可能是一件昂贵的事情。
swalex 2015年

2

如果您具有泛型类型参数,那么Jeff Bridgman的答案就是最好的答案。如果只有一个Type对象表示要构造的类型,则可以Activator.CreateInstance(Type)像Alex Lyman所建议的那样使用,但是有人告诉我它很慢(不过我个人没有对其进行概要分析)。

但是,如果您发现自己经常构建这些对象,则可以使用动态编译的Linq表达式进行更雄辩的方法:

using System;
using System.Linq.Expressions;

public static class TypeHelper
{
    public static Func<object> CreateDefaultConstructor(Type type)
    {
        NewExpression newExp = Expression.New(type);

        // Create a new lambda expression with the NewExpression as the body.
        var lambda = Expression.Lambda<Func<object>>(newExp);

        // Compile our new lambda expression.
        return lambda.Compile();
    }
}

只需致电返回给您的代表即可。您应该缓存此委托,因为不断重新编译Linq表达式可能会很昂贵,但是如果您缓存该委托并每次重用它,则它可能会非常快!我个人使用按类型索引的静态查找字典。当您处理序列化的对象时,该功能可能会派上用场,在这些对象中您可能只知道Type信息。

注意:如果类型不可构造或没有默认构造函数,则可能会失败!


0

如果只想获取默认的构造函数以实例化该类,并且将类型作为函数的泛型类型参数来获取,则可以执行以下操作:

T NewItUp<T>() where T : new()
{
   return new T();
}

-2

您可能想尝试FormatterServices.GetUninitializedObject(Type)这比Activator.CreateInstance更好

然而,这种方法不调用对象的构造函数,所以如果你有初始值设定,这是不行的检查MSDN为这件事 http://msdn.microsoft.com/en-us/library/system.runtime .serialization.formatterservices.getuninitializedobject.aspx

这里还有另一种方式 http://www.ozcandegirmenci.com/post/2008/02/Create-object-instances-Faster-than-Reflection.aspx

但是,如果对象具有参数构造函数,则此操作将失败

希望这可以帮助

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.