VS 2022 17.1 不会构建 C# 10 结构体 (CS8983)。17.0.5 喜欢它。发生了什么?

Joe*_*Joe 8 c# visual-studio-2022 c#-10.0

我在 VS2022 中构建了这个 C# 结构,直到昨晚我从版本 17.0.5 升级到 17.1

internal struct RoutineSettings
{
    public bool Show { get; set; } = true;
    public ShapeType PreferredShapeType { get; set; } = ShapeType.None;
}
Run Code Online (Sandbox Code Playgroud)

ShapeType只是一个枚举)。

升级后,我收到此错误:

error CS8983: A 'struct' with field initializers must include an explicitly declared constructor.
Run Code Online (Sandbox Code Playgroud)

解释很简单。但由于这段代码在我感到困惑之前执行得很好。

  1. 是编译器错误吗?
  2. 这是编译器到目前为止未能检查的真正语言要求吗?

如果正确答案是#2,这就引出了一个问题:为什么这是一个要求?为什么需要它?因为当我“修复”它时,修复似乎毫无意义。我刚刚添加了一个空的默认构造函数:

internal struct RoutineSettings
{
    public RoutineSettings() { }
    public bool Show { get; set; } = true;
    public ShapeType PreferredShapeType { get; set; } = ShapeType.None;
}
Run Code Online (Sandbox Code Playgroud)

现在我的代码再次构建。当它什么都不做时我为什么需要这个?

PMF*_*PMF 5

这确实是以前版本中的编译器错误。直到 C# 9.0,结构体都不允许有默认构造函数,并且它实际上不会生成,这与类不同,在类中,当没有定义构造函数时会自动生成默认构造函数。这允许在不调用代码的情况下创建值类型(只需清空内存)。显然,他们希望明确这一更改,因为无论默认构造函数是否存在,它确实会对生成的代码产生影响。请注意,在您的示例中,默认构造函数不为空,因为任何字段初始值设定项都会隐式添加到构造函数代码中。因此,在 C# 10 中,当声明构造函数时,就会生成它,否则它将远离生成的 IL。

另请注意,使用此功能时存在很多陷阱。分配结构体数组时,默认构造函数仍然不执行:

        [Fact]
        public void StructCtorIsExecuted()
        {
            var r = new RoutineSettingsWithDefaultCtor();
            Assert.Equal(10, r.PreferredShapeType);

            RoutineSettingsWithDefaultCtor[] array = new RoutineSettingsWithDefaultCtor[10];
            Assert.Equal(0, array[0].PreferredShapeType); // <-- When allocating an array, the default ctor is NOT executed
        }

        internal struct RoutineSettingsWithDefaultCtor
        {
            public RoutineSettingsWithDefaultCtor()
            {
                PreferredShapeType = 10;
            }

            public bool Show { get; set; } = true;
            public int PreferredShapeType { get; set; } = 2;
        }
}
Run Code Online (Sandbox Code Playgroud)

这里描述了更多问题:https://davidshergilashvili.space/2021/09/05/c-10-struct-type-can-define-default-constructor/