【问题标题】:Most efficient way to get default constructor of a Type获取类型的默认构造函数的最有效方法
【发布时间】:2008-09-26 22:28:07
【问题描述】:

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

我正在按照下面的代码行进行一些思考,但似乎应该有一种更简单更有效的方法来做到这一点。

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

【问题讨论】:

    标签: c# .net reflection


    【解决方案1】:
    type.GetConstructor(Type.EmptyTypes)
    

    【讨论】:

    • 你从未看过的静态成员......这太棒了。
    • 私人会员也不看。假设您只需要 public 那么这似乎是最简单的。然而,它是最快的吗?我正在做一个测试以找出答案。
    • 在测量了这种方法与我使用 MeasureIt (msdn.microsoft.com/en-us/magazine/cc500596.aspx) 的方法之后,除了最简单的情况外,这种方法在所有情况下都更快,即使这样它也几乎没有变慢。所以这既是最简单也是最快的。谢谢!
    【解决方案2】:

    如果您确实需要 ConstructorInfo 对象,请参阅Curt Hagenlocher's answer

    另一方面,如果您真的只是想在运行时从System.Type 创建一个对象,请参阅System.Activator.CreateInstance——它不仅仅是面向未来的(Activator 处理的细节比ConstructorInfo.Invoke 更多),它也不那么难看。

    【讨论】:

    • 潜在危险的建议,因为某些对象没有默认构造函数(字符串为一)。因此,如果您只是随便调用它,您可能会得到一个 MissingMethod 异常。在调用此方法之前,我实际上必须检查默认构造函数。
    • 正如 cunningdave 所写,您很可能希望至少捕获并优雅地处理此方法可能抛出的异常集的一部分,这将使调用再次变得不那么美观。另一方面,使用 ConstructorInfo 的解决方案实际上看起来有点丑陋,但允许您处理所有这些异常情况,而无需先抛出和捕获异常,这可能是一件代价高昂的事情。
    【解决方案3】:

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

    但是,如果您发现自己非常频繁地构造这些对象,则使用动态编译的 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 表达式可能会很昂贵,但是如果你缓存委托并每次都重用它,它会非常快!我个人使用按类型索引的静态查找字典。当您处理可能只知道类型信息的序列化对象时,此函数会派上用场。

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

        你想试试 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

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

        希望对你有帮助

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-11-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-19
          • 2013-02-03
          • 1970-01-01
          相关资源
          最近更新 更多