解决构造函数声明中的错误和警告

本文介绍以下编译器错误:

  • CS0514静态构造函数不能有显式的“this”或“base”构造函数调用。
  • CS0515:不允许在静态构造函数中使用 访问修饰符。
  • CS0516构造函数“constructor”无法调用其自身。
  • CS0517“class”没有基类,无法调用基构造函数。
  • CS0522结构无法调用基类构造函数。
  • CS0526接口不能包含构造函数。
  • CS0568结构不能包含显式无参数构造函数。
  • CS0710静态类不能有实例构造函数。
  • CS0768构造函数无法通过另一个构造函数自行调用。
  • CS8054枚举不能包含显式无参数构造器。
  • CS8091不能是外部的,也不能具有构造函数初始值设定项。
  • CS8861意外参数列表。
  • CS8862在具有参数列表的类型中声明的构造函数必须具有“this”构造函数初始值设定项。
  • CS8358无法使用属性构造函数,因为它具有“in”参数。
  • CS8867基类型“{0}”中找不到可访问的复制构造函数。
  • CS8868记录中的复制构造函数必须调用基的复制构造函数;如果记录继承自对象,则必须调用无参数对象构造函数。
  • CS8878复制构造函数“{0}”必须公开或受保护,因为记录未密封。
  • CS8910主构造函数与合成复制构造函数冲突。
  • CS8958无参数结构构造函数必须为“public”。
  • CS8982在“结构体”中带有参数列表声明的构造函数必须有一个“this”初始化器,用于调用主构造函数或显式声明的其他构造函数。
  • CS8983具有字段初始值设定项的“结构”必须包含显式声明的构造函数。
  • CS9105不能在此上下文中使用主构造函数参数。
  • CS9106此上下文中的类型和参数之间的标识符不明确。
  • CS9108无法使用在匿名方法、lambda 表达式、查询表达式或本地函数中具有类似 ref 类型的参数。
  • CS9109不能在实例成员内使用 refoutin 主构造函数参数。
  • CS9110无法在实例成员中使用具有类似于 ref 类型的主构造函数参数。
  • CS9111结构实例成员内的匿名方法、lambda 表达式、查询表达式和本地函数无法访问主构造函数参数。
  • CS9112匿名方法、lambda 表达式、查询表达式和结构内的本地函数无法访问实例成员内也使用的主构造函数参数。
  • CS9114:不能为只读类型的主构造函数参数赋值(在该类型的仅限 init 的资源库中或变量初始值设定项除外)。
  • CS9115可写引用无法返回只读类型的主要构造函数参数。
  • CS9116无法将只读类型的主构造函数参数用作 ref 或 out 值(在该类型的仅限 init 的资源库中或变量初始值设定项除外)。
  • CS9117:不能修改只读类型的主构造函数参数的成员(在该类型的仅限 init 的资源库中或变量初始值设定项除外)。
  • CS9118只读类型的主构造函数参数的成员不能通过可写引用返回。
  • CS9119不能将只读类型的主构造函数参数的成员用作 refout 值(在该类型的仅限 init 的资源库中或变量初始值设定项除外)。
  • CS9120无法按引用返回主构造函数参数。
  • CS9121结构主构造函数参数的类型会导致结构布局中的循环。
  • CS9122意外的参数列表。
  • CS9136无法在实例成员内使用类型的主构造函数参数。

此外,本文还介绍了以下警告:

  • CS0824构造函数“name”标记为外部对象。
  • CS9107参数被捕获到封闭类型的状态,其值也传递给基构造函数。也可以由基类捕获该值。
  • CS9113参数未读。
  • CS9124参数被捕获到封闭类型的状态中,其值还会用于初始化字段、属性或事件。
  • CS9179主构造函数参数被基成员隐藏

静态构造函数

  • CS0514静态构造函数不能具有显式的“this”或“base”构造函数调用。
  • CS0515静态构造函数中不允许出现访问修饰符。

最多可以编写一个类型的静态构造函数。 静态构造函数的声明必须遵循以下规则:

  • 静态构造函数具有 static 修饰符,但没有其他修饰符,例如 publicprotectedprivateinternal
  • 静态构造函数必须是无参数构造函数。
  • 静态构造函数不得调用 base()this()。 如果基类包含静态构造函数,运行时会自动调用它。

构造函数声明

  • CS0526接口不能包含构造函数。
  • CS0710静态类不能有实例构造函数。
  • CS8054枚举不能包含显式的无参数构造函数。
  • CS8358无法使用属性构造函数,因为它具有“in”参数。
  • CS8091构造函数不能是外部构造函数,并且具有构造函数初始值设定项。

构造函数仅允许在 classstruct 类型中使用,包括 record classrecord struct 类型。 不能在 enuminterface 类型中定义它们。 此外,属性 类类型无法声明 in 参数。 而是按值传递参数。

可以声明 extern 构造函数,但不能使用 base()this() 构造函数调用从声明 extern的构造函数调用另一个构造函数。

此外,可以为构造函数声明生成以下警告:

  • CS0824构造函数标记为外部对象。

当构造函数标记为 extern时,编译器无法保证构造函数存在。 因此,编译器将生成此警告。

结构类型中的构造函数

  • CS0568结构不能包含显式无参数构造函数。
  • CS8958无参数结构构造函数必须为“public”。
  • CS8982具有参数列表的“结构”中声明的构造函数必须具有调用主构造函数或显式声明的构造函数的“this”初始值设定项。
  • CS8983具有字段初始值设定项的“结构”必须包含显式声明的构造函数。

C# 中的最近功能消除了对 struct 类型的早期限制。 在旧版 C# 中声明无参数实例构造函数时,将生成 CS0568。 在 C# 的较新版本中,可以声明一个无参数的显式实例构造函数。 该显式无参数构造函数必须是public。 如果 struct 声明了任何字段初始化表达式,你还必须声明显式实例构造函数。 此构造函数可以是具有空正文的无参数构造函数。

struct 类型声明主构造函数(包括 record struct 类型)时,除无参数构造函数以外的所有其他实例构造函数都必须使用 this()调用主构造函数或其他显式声明的构造函数。

使用 basethis 进行构造函数调用

  • CS0516构造函数无法调用其自身。
  • CS0517类没有基类,并且无法调用基构造函数。
  • CS0522结构无法调用基类构造函数。
  • CS0768构造函数无法通过另一个构造函数自行调用。

可以使用 base()this() 完成一个构造函数对另一个相同类型或基类型的构造函数的调用。 调用构造函数可以最大程度地减少重复的构造函数逻辑。 在使用 this()base()调用另一个构造函数时,必须遵循以下规则:

  • 构造函数不能通过另一个构造函数直接或间接调用自身。 例如,以下代码是非法的:

    public class C
    {
      public C() : this() // Error!
      {
      }
    }
    
    public class C2
    {
      public class C2() : this(10) {}
    
      public class C2(int capacity) : this() 
      {
          _capacity = capacity;
      }
    
      private int _capacity;
    }
    ``
    
    
  • 结构类型无法调用 base()System.Object也不能。

记录和复制构造函数

  • CS8867基类型中找不到可访问的复制构造函数。
  • CS8868记录中的复制构造函数必须调用基的复制构造函数;如果记录继承自对象,则必须调用无参数对象构造函数。
  • CS8878复制构造函数必须是公共的或受保护的,因为该记录未密封。
  • CS8910主构造函数与合成复制构造函数冲突。

record 修饰符添加到 structclass 类型会创建记录。 记录包括编译器合成的复制构造函数。 可以自行编写显式复制构造函数,但它必须遵循以下规则:

  • 复制构造函数必须是 publicprotected,除非类型为 sealed
  • 复制构造函数必须调用 base() 复制构造函数,除非基类为 System.Object
  • 此外,基类型必须具有复制构造函数。 record 类型始终具有复制构造函数。

主构造函数声明

当主构造函数违反类和结构的主要构造函数上的一个或多个规则时,编译器将发出以下错误:

  • CS8861意外的参数列表。
  • CS8862在具有参数列表的类型中声明的构造函数必须具有“this”构造函数初始值设定项。
  • CS9105不能在此上下文中使用主构造函数参数。
  • CS9106标识符在此上下文中的类型和参数之间不明确。
  • CS9108无法使用在匿名方法、lambda 表达式、查询表达式或本地函数中具有类似 ref 类型的参数。
  • CS9109不能在实例成员内使用 refoutin 主构造函数参数。
  • CS9110无法在实例成员中使用具有 ref 类似类型的主构造函数参数。
  • CS9111结构实例成员内的匿名方法、lambda 表达式、查询表达式和本地函数无法访问主构造函数参数。
  • CS9112匿名方法、lambda 表达式、查询表达式和结构内的本地函数无法访问实例成员内也使用的主构造函数参数。
  • CS9114不能为只读类型的主构造函数参数赋值(在该类型的仅限 init 的资源库中或变量初始值设定项除外)。
  • CS9115可写引用无法返回只读类型的主要构造函数参数。
  • CS9116无法将只读类型的主构造函数参数用作 refout 值(在该类型的仅限 init 的资源库中或变量初始值设定项除外)。
  • CS9117不能修改只读类型的主构造函数参数的成员(在该类型的仅限 init 的资源库中或变量初始值设定项除外)。
  • CS9118只读类型的主构造函数参数的成员不能通过可写引用返回。
  • CS9119不能将只读类型的主构造函数参数的成员用作 refout 值(在该类型的仅限 init 的资源库中或变量初始值设定项除外)。
  • CS9120无法按引用返回主构造函数参数。
  • CS9121类型的结构主构造函数参数导致结构布局中出现循环。
  • CS9122意外的参数列表。
  • CS9124参数被捕获到封闭类型的状态中,其值也被用于初始化字段、属性或事件。
  • CS9136无法在实例成员内使用类型的主构造函数参数。

在类或结构中使用主构造函数时,每个显式声明的构造函数都必须使用 : this(...) 适当的参数列表调用主构造函数。 这可确保始终调用主构造函数。 有关主要构造函数的详细信息,请参阅编程指南中有关 实例构造函数 的文章。

主构造函数参数在该类型的主体范围内。 编译器可以合成一个字段,该字段存储用于成员或字段初始值设定项的参数。 由于主构造函数参数可以复制到字段,因此适用以下限制:

  • 主要构造函数可以在 structclass 类型上声明,但不能在 interface 类型上声明。
  • 主构造函数参数不能在 base() 构造函数调用中使用,除非作为主构造函数的一部分。
  • 无法在 lambda 表达式、查询表达式或本地函数中访问 ref struct 类型的主要构造函数参数。
  • 如果类型不是 ref struct,则实例成员中无法访问 ref struct 参数。
  • ref struct 类型中,不能在任何实例方法或属性访问器中使用具有 inrefout 修饰符的主要构造函数参数。

结构类型对主要构造函数参数具有以下额外限制:

  • 无法在 lambda 表达式、查询表达式或本地函数中捕获主构造函数参数。
  • 主构造函数参数不能由引用返回(ref 返回或 readonly ref 返回)。

仅限只读的结构类型对主要构造函数参数具有以下额外限制:

  • 主构造函数参数及其成员无法在 readonly 结构中重新分配。
  • 不能在 ref 结构中对主构造函数参数及其成员进行 readonly 返回。
  • 主构造函数的参数及其成员不能作为任何方法的 refout 参数。

在所有这些情况下,对主要构造函数参数的限制与这些类型中的数据字段的限制一致。 限制是因为主要构造函数参数可能转换为类型中的合成字段。 因此,主构造函数参数必须遵循应用于该合成字段的规则。

派生的主构造函数通过向基构造函数提供参数来调用基本主构造函数。 必须使用派生构造函数声明中的参数名称。

这些警告提供有关捕获或隐藏的主构造函数参数的指导。

  • CS9107参数被捕获到封闭类型的状态,并且其值也传递给基构造函数。也可以由基类捕获该值。 此警告指示代码可能分配了主构造函数参数的两个副本。 由于参数传递给基类,因此基类可能会使用它。 由于派生类访问它,因此它可能具有同一参数的第二个副本。 这种额外的存储可能不是预期的。
  • CS9113参数未被读取。 此警告表明你的类从未引用主构造函数,甚至没有将其传递给基本主构造函数。 可能用不着。
  • CS9124参数捕获到封闭类型的状态,并且其值还用于初始化字段、属性或事件。 此警告指示嵌套类型的构造函数参数也由封闭类型捕获。 该参数可能存储两次。
  • CS9179主构造函数参数被基成员隐藏