Tenía esta estructura C# que se estaba construyendo en VS2022 literalmente hasta anoche cuando actualicé de la versión 17.0.5 a la 17.1
internal struct RoutineSettings { public bool Show { get; set; } = true; public ShapeType PreferredShapeType { get; set; } = ShapeType.None; } ( ShapeType es solo una enumeración).
Después de la actualización, aparece este error:
error CS8983: A 'struct' with field initializers must include an explicitly declared constructor.La explicación es bastante sencilla. Pero dado que este código se ejecutó bien antes de que esté confundido.
Si la respuesta correcta es la #2, surge la pregunta ¿por qué es un requisito? ¿Por qué es necesario? Porque cuando lo "arreglé", la solución parecía inútil. Acabo de agregar un constructor predeterminado vacío:
internal struct RoutineSettings { public RoutineSettings() { } public bool Show { get; set; } = true; public ShapeType PreferredShapeType { get; set; } = ShapeType.None; }Y ahora mi código se construye de nuevo. ¿Por qué necesitaría esto cuando no hace nada?
Esto realmente parece haber sido un error del compilador en la versión anterior. Hasta C# 9.0, a las estructuras no se les permitía tener un ctor predeterminado y realmente no se generaba, a diferencia de las clases, donde el ctor predeterminado se generaba automáticamente cuando no se definió ningún constructor. Esto permite crear tipos de valor sin llamar al código (simplemente anulando la memoria). Aparentemente, querían hacer este cambio explícito, porque realmente hace una diferencia en el código generado, ya sea que exista o no el constructor predeterminado. Tenga en cuenta que en su ejemplo, el constructor predeterminado no está vacío, porque cualquier inicializador de campo se agrega implícitamente al código del constructor. Entonces, en C# 10, cuando se declara el constructor, se genera; de lo contrario, se deja fuera del IL generado.
También tenga en cuenta que hay un montón de trampas al usar esta función. El ctor predeterminado todavía no se ejecuta cuando se asigna una matriz de la estructura:
[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; } }algunos problemas más se describen aquí: https://davidshergilashvili.space/2021/09/05/c-10-struct-type-can-define-default-constructor/
Eso no es un error, sino una nueva opción de diseño para C#:
https://github.com/dotnet/sdk/issues/23971
Solución:
Defina un constructor público sin parámetros y resolverá el problema.
Por ejemplo, antes:
public struct Abc { public int Num1 = 5; }Después:
public struct Abc { public int Num1 = 5; public Abc() {} // <--- Parameter-less default constructor }