VS 2022 17.1 不会构建 C# 10 结构 (CS8983)。 17.0.5 喜欢它。发生了什么?
VS 2022 17.1 wont build C# 10 struct (CS8983). 17.0.5 liked it. What happened?
直到昨晚我从版本 17.0.5 升级到 17.1 之前,我一直在 VS2022 中构建这个 C# 结构
internal struct RoutineSettings
{
public bool Show { get; set; } = true;
public ShapeType PreferredShapeType { get; set; } = ShapeType.None;
}
(ShapeType
只是一个枚举)。
升级后,出现此错误:
error CS8983: A 'struct' with field initializers must include an explicitly declared constructor.
解释很简单。但是由于这段代码在我感到困惑之前执行得很好。
- 是不是编译器出错了?
- 这是一个真正的语言要求,编译器直到现在才检查失败吗?
如果正确答案是#2,它会提出问题为什么这是一项要求?为什么需要它?因为当我“修复”它时,修复似乎毫无意义。我刚刚添加了一个空的默认构造函数:
internal struct RoutineSettings
{
public RoutineSettings() { }
public bool Show { get; set; } = true;
public ShapeType PreferredShapeType { get; set; } = ShapeType.None;
}
现在我的代码再次构建。当它什么都不做时我为什么需要它?
这似乎确实是以前版本中的编译器错误。在 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;
}
}
这里描述了更多问题:https://davidshergilashvili.space/2021/09/05/c-10-struct-type-can-define-default-constructor/
这不是错误,而是 C# 的新设计选择:
https://github.com/dotnet/sdk/issues/23971
解法:
定义一个 public parameter-less 构造函数,它将解决问题。
例如,之前:
public struct Abc
{
public int Num1 = 5;
}
之后:
public struct Abc
{
public int Num1 = 5;
public Abc() {} // <--- Parameter-less default constructor
}
直到昨晚我从版本 17.0.5 升级到 17.1 之前,我一直在 VS2022 中构建这个 C# 结构
internal struct RoutineSettings
{
public bool Show { get; set; } = true;
public ShapeType PreferredShapeType { get; set; } = ShapeType.None;
}
(ShapeType
只是一个枚举)。
升级后,出现此错误:
error CS8983: A 'struct' with field initializers must include an explicitly declared constructor.
解释很简单。但是由于这段代码在我感到困惑之前执行得很好。
- 是不是编译器出错了?
- 这是一个真正的语言要求,编译器直到现在才检查失败吗?
如果正确答案是#2,它会提出问题为什么这是一项要求?为什么需要它?因为当我“修复”它时,修复似乎毫无意义。我刚刚添加了一个空的默认构造函数:
internal struct RoutineSettings
{
public RoutineSettings() { }
public bool Show { get; set; } = true;
public ShapeType PreferredShapeType { get; set; } = ShapeType.None;
}
现在我的代码再次构建。当它什么都不做时我为什么需要它?
这似乎确实是以前版本中的编译器错误。在 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;
}
}
这里描述了更多问题:https://davidshergilashvili.space/2021/09/05/c-10-struct-type-can-define-default-constructor/
这不是错误,而是 C# 的新设计选择:
https://github.com/dotnet/sdk/issues/23971
解法:
定义一个 public parameter-less 构造函数,它将解决问题。
例如,之前:
public struct Abc
{
public int Num1 = 5;
}
之后:
public struct Abc
{
public int Num1 = 5;
public Abc() {} // <--- Parameter-less default constructor
}