【问题标题】:Why default constructor does not appear for value types?为什么值类型没有出现默认构造函数?
【发布时间】:2020-10-23 01:10:28
【问题描述】:

下面的 sn-p 给了我一个类型的构造函数和方法的列表。

static void ReflectOnType(Type type)
{
    Console.WriteLine(type.FullName);
    Console.WriteLine("------------");
    List<ConstructorInfo> constructors =
            type.GetConstructors(BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic |BindingFlags.Instance | BindingFlags.Default).ToList();

    List<MethodInfo> methods = type.GetMethods().ToList();

    Type baseType = type.BaseType;

    while (baseType != null)
    {
            constructors.AddRange(baseType.GetConstructors(BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic |
                              BindingFlags.Instance | BindingFlags.Default));
            methods.AddRange(baseType.GetMethods());
            baseType = baseType.BaseType;
    }

    Console.WriteLine("Reflection on {0} type", type.Name);

    for (int i = 0; i < constructors.Count; i++)
    {
         Console.Write("Constructor: {0}.{1}", constructors[i].DeclaringType.Name, constructors[i].Name);
         Console.Write("(");
         ParameterInfo[] parameterInfos = constructors[i].GetParameters();
         if (parameterInfos.Length > 0)
         {
             for (int j = 0; j < parameterInfos.Length; j++)
             {
                 if (j > 0)
                 {
                     Console.Write(", ");
                 }
                 Console.Write("{0} {1}", parameterInfos[j].ParameterType, parameterInfos[j].Name);
             }
         }
         Console.Write(")");

         if (constructors[i].IsSpecialName)
         {
             Console.Write(" has 'SpecialName' attribute");
         }
         Console.WriteLine();
     }
     Console.WriteLine();

     for (int i = 0; i < methods.Count; i++)
     {
         Console.Write("Method: {0}.{1}", methods[i].DeclaringType.Name, methods[i].Name);
         // Determine whether or not each field is a special name.
         if (methods[i].IsSpecialName)
         {
             Console.Write(" has 'SpecialName' attribute");
         }
         Console.WriteLine();
     }
 }

但是当我将一个“int”类型传递给这个方法时,为什么我在输出中看不到隐式构造函数?或者,如何修改上面的代码以列出默认构造函数(以防我的代码中缺少某些内容)。

【问题讨论】:

标签: c# .net


【解决方案1】:

在 C#(和大多数 CLI 语言)中 - 禁止在结构上指定无参数构造函数,因此,在 C#(和大多数其他 .NET 语言)中创建的结构甚至不会在 IL 中定义无参数构造函数. CLR 总是使用定义的规则初始化值类型(基本上,用零等价物填充所有值),而 C# 将其作为唯一选项强制执行。

由于 C# 生成的结构中不存在默认的无参数构造函数,因此在使用反射时不会显示。

【讨论】:

  • Reed,您有任何 MSDN 文档或有关这方面的文章,以便我了解更多信息吗?
  • @Arun: msdn.microsoft.com/en-us/library/aa288208(VS.71).aspx "结构不能包含显式的无参数构造函数。结构成员会自动初始化为其默认值。"
  • @Arun: Current - msdn.microsoft.com/en-us/library/s1ax56ch.aspx - “每个值类型都有一个隐式默认构造函数,用于初始化该类型的默认值。”
  • 很好奇 - 为什么要投反对票?这是真的对于 C# - 授予,您可以在 CLI 中定义一个构造函数,在这种情况下,它确实通过反射显示 - 但从 C# 中是不可能的(这是问题上的标签...)
  • 可以被“覆盖”,只是不能在 C# 中。但它显然不是很有用,因为 CLR 并不总是在您期望的地方运行它。
【解决方案2】:

如果您想使用任何构造函数,您可以通过以下方式获取构造函数列表

var consturctorList = type.GetContructors();

如果你的值类型是一个没有显式定义构造函数的结构,你会在上面得到一个空列表,因为隐式构造函数不能在反射中搞乱它,你可以使用反序列化方法

FormatterServices.GetUninitializedObject(Type type)

【讨论】:

    【解决方案3】:

    这是 C# 和 CLI 规范之间的差异。 C# 说所有值类型都有一个(不可覆盖的)默认无参数构造函数,但 CLI 并非如此。

    在许多情况下,运行时不会运行默认构造函数,即使它存在(这是合理的,因为大多数以 CIL 为目标的语言不允许你编写一个);用零填充结构后什么都不做。这是 Jon Skeet 的 interesting article,它尝试将无参数构造函数破解为结构 - 它有时运行,有时不运行,具体取决于上下文。

    无论如何,反射 API 没有在该类型上显示这样一个无参数构造函数的原因是因为没有。

    【讨论】:

      【解决方案4】:

      为什么值类型没有出现默认构造函数?

      简而言之,因为值类型的构造函数不存在。

      更详细的解释here

      据我所知,CLR 没有定义默认构造函数, 引用类型的默认构造函数由 C# 编译器生成 本身(或其他语言编译器)。所以CLR没有默认 既不是引用类型也不是值类型的构造函数。

      对于引用类型,C# 定义了默认的无参数 ctor ,它 调用基类ctor。但这是 C# 编译器发出的工作 这个默认的 ctor 代码,没有 CLR。现在对于 valuetype 这不会发生 (即编译器没有发出默认的ctor)

      所以,既然 "int" 是 Valye 类型,就不存在任何构造函数。

      【讨论】:

        猜你喜欢
        • 2017-05-02
        • 2018-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-01
        • 2013-03-20
        相关资源
        最近更新 更多