【问题标题】:How do I check if a type provides a parameterless constructor?如何检查类型是否提供无参数构造函数?
【发布时间】:2011-06-08 12:54:26
【问题描述】:

我想检查在运行时已知的类型是否提供无参数构造函数。 Type 类没有产生任何有希望的东西,所以我假设我必须使用反射?

【问题讨论】:

  • 旁注:无参数构造函数有一个通用约束。
  • 是类型 only 提供无参数构造函数还是提供无参数构造函数的问题?
  • 后者。我不介意其他演员的存在。

标签: c# .net reflection constructor types


【解决方案1】:

是的,您必须使用反射。但是当你使用GetType()时你已经这样做了

类似:

var t = x.GetType();
var c = t.GetConstructor(new Type[0]);
if (c != null) ...

【讨论】:

    【解决方案2】:

    这应该可行:

       myClass.GetType().GetConstructors()
                        .All(c=>c.GetParameters().Length == 0)
    

    【讨论】:

    • 不是我的意思,但请不要删除 - 这是一个相关问题和一个很好的信息。
    • 确实,OP 请求的正确表达应该是myClass.GetType().GetConstructors().Any(c=>c.GetParameters().Length == 0)。请注意使用 Any 而不是 All
    【解决方案3】:

    Type 反射。你可以这样做:

    Type theType = myobject.GetType(); // if you have an instance
    // or
    Type theType = typeof(MyObject); // if you know the type
    
    var constructor = theType.GetConstructor(Type.EmptyTypes);
    

    如果无参数构造函数不存在,它将返回 null。


    如果你还想找到私有构造函数,使用稍长的:

    var constructor = theType.GetConstructor(
      BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, 
      null, Type.EmptyTypes, null);
    

    值类型有一个警告,aren't allowed to have a default constructor。您可以使用Type.IsValueType 属性检查您是否有值类型,并使用Activator.CreateInstance(Type) 创建实例;

    【讨论】:

    • 这不会找到私人演员仅供参考
    • 又短又甜。来自未来的 +1。
    【解决方案4】:

    是的,你必须使用反射。

    object myObject = new MyType();
    Type type = myObject.GetType();
    ConstructorInfo conInfo = type.GetConstructor(new Type[0]);
    

    【讨论】:

      【解决方案5】:

      根据您的情况,您还可以使用泛型类型限制:

      public void DoSomethingWith<T>(T myObject) where T:new() {...}
      

      上述方法声明将参数类型限制为可以使用无参数构造函数实例化的任何对象。这里的好处是编译器会捕捉到任何尝试将该方法与没有无参数构造函数的类一起使用的尝试,因此只要在编译时知道类型,这将起作用并提醒您之前的问题。

      当然,如果类型真的只在运行时才知道(即,您使用 Activator.CreateInstance() 根据字符串或构造的类型实例化对象),那么这对您没有帮助。我通常使用反射作为绝对的最后选择,因为一旦你进入动态地带,你几乎必须留在动态地带;动态实例化某些东西然后开始静态处理它通常很困难甚至更混乱。

      【讨论】:

      • 实际上,有一个非常有用的模式可以连接静态和动态调用:静态通用缓存类 [e.g. EqualityComparer.Default&lt;T&gt;]。对于任何给定的类型T,只需使用一次反射来构建一个对象,该对象的实例类型将被静态已知以符合任何所需的约束,并将对它的引用存储在不施加任何约束的字段中来电者可能无法提供。
      【解决方案6】:
      type.GetConstructor(Type.EmptyTypes) != null
      

      structs 会失败。最好扩展它:

      public static bool HasDefaultConstructor(this Type t)
      {
          return t.IsValueType || t.GetConstructor(Type.EmptyTypes) != null;
      }
      

      成功,因为即使enums 也有默认的无参数构造函数。由于没有进行反射调用,因此值类型也略微加快了速度。

      【讨论】:

        【解决方案7】:

        我需要计算带有 only 可选参数的构造函数,这与真正的无参数构造函数相同。为此:

        myClass.GetType().GetConstructors()
            .All(c => c.GetParameters().Length == 0 || c.GetParameters().All(p => p.IsOptional))
        

        【讨论】:

          【解决方案8】:

          如果有人对“官方”版本感兴趣,可以通过.NET Reflector找到以下内容:

          来自:System.Activities.Presentation.TypeUtilities
          System.Activities.Presentation.dll,版本=4.0.0.0

          public static bool CanCreateInstanceUsingDefaultConstructor(this Type t) => 
                          t.IsValueType || !t.IsAbstract && t.GetConstructor(Type.EmptyTypes) != null;
          

          注意检查t.IsAbstract,本页其他地方未提及。

          如果您想对一个堆栈帧进行微优化,也可以按如下方式扩展 GetConstructor 调用:

          …t.GetConstructor(BindingFlags.Public|BindingFlags.Instance, null, Type.EmptyTypes, null)…
          

          【讨论】:

            【解决方案9】:

            要获取具有更多可选参数或完全为空的构造函数,请使用:

                typeof(myClass)
                .GetConstructors()
                .OrderBy(x => x.GetParameters().Length - x.GetParameters().Count(p => p.IsOptional))
                .FirstOrDefault();
            

            【讨论】:

              猜你喜欢
              • 2020-05-13
              • 1970-01-01
              • 1970-01-01
              • 2012-01-25
              • 2017-08-13
              • 1970-01-01
              • 2015-06-20
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多