Update:在 C# 10+ (.NET 6+) 中,此限制被解除。你现在can结构上有默认构造函数,并且您还can就地初始化字段和属性。像编写一个类一样编写您的结构,它将起作用:
public struct OptionsStruct
{
public int ItemA { get; set; } = 2;
public int ItemQ { get; set; } = 2;
}
SetOptions(new OptionsStruct()
{
ItemA = 3,
// ...all other fields have default values.
});
但是,有两个问题需要注意:
-
如果结构上没有构造函数或无参数构造函数,则字段和属性初始化将正常工作。但是,如果您有带参数的构造函数但没有无参数构造函数,它们将不起作用。如果你有一个带参数的构造函数,也要写一个无参数的构造函数(即使它是空的),所以当你写new MyStruct()
,字段和属性将按照您的预期进行初始化。 (此行为是为了与以前的行为(当所有参数都是可选时不调用构造函数)保持向后兼容性。有关示例,请参阅此答案的最后一个代码块。)
public struct NoConstructor
{
public int Item { get; set; } = 42;
}
public struct ParameterlessConstructor
{
public int Item { get; set; } = 42;
public ParameterlessConstructor() { }
}
public struct WithParameterConstructor
{
public int Item { get; set; } = 42;
public WithParameterConstructor(int item)
{
Item = item;
}
}
public struct BothConstructors
{
public int Item { get; set; } = 42;
public BothConstructors() { }
public BothConstructors(int item)
{
Item = item;
}
}
Console.WriteLine(new NoConstructor().Item); // 42
Console.WriteLine(new ParameterlessConstructor().Item); // 42
Console.WriteLine(new WithParameterConstructor().Item); // 0
Console.WriteLine(new BothConstructors().Item); // 42
-
无参数构造函数不保证始终被调用,因此不要依赖始终初始化的字段和属性。如果您创建一个结构体数组,例如new MyStruct[5]
,或者如果你使用default
or default(MyStruct)
,不会调用构造函数,并且字段和属性将初始化为默认值(0
or false
or null
),就像 C# 10 之前的情况一样。
public struct MyStruct
{
public int FortyTwo { get; } = 42;
public int GetFortyThree()
{
return FortyTwo + 1;
}
}
public class SomeClass
{
MyStruct myStruct; // not initialized, same as default(MyStruct)
public int GetFortyThree()
{
return myStruct.GetFortyThree();
}
}
Console.WriteLine(new MyStruct().GetFortyThree()); // 43
Console.WriteLine(default(MyStruct).GetFortyThree()); // 1
var array = new MyStruct[5];
Console.WriteLine(array[0].GetFortyThree()); // 1
Console.WriteLine(new SomeClass().GetFortyThree()); // 1
以下是有关 C# 10 / .NET 6 新功能的文档链接:无参数构造函数和字段初始值设定项 https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/struct#parameterless-constructors-and-field-initializers
对于 C# 9 及更低版本,请继续阅读...
的限制struct
是你不能拥有default构造函数。因此,您不能为字段和属性设置默认值(因为它被编译到默认构造函数中)。
But you can有一个非默认构造函数,即带有参数的构造函数。
所以你可以有一个struct
像这样:
public struct OptionsStruct
{
public int ItemA { get; set; }
public int ItemQ { get; set; }
public OptionsStruct(bool useDefaults)
{
if (useDefaults)
{
ItemA = 2;
ItemQ = 2;
}
else
{
ItemA = 0;
ItemQ = 0;
}
}
}
并按照您所写的那样使用它:
SetOptions(new OptionsStruct(useDefaults:true)
{
ItemA = 3,
// ...all other fields have default values.
});
另一种方法是有一个static
设置默认值的方法:
public struct OptionsStruct
{
public int ItemA { get; set; }
public int ItemQ { get; set; }
public static OptionsStruct GetDefault()
{
return new OptionsStruct()
{
ItemA = 2;
ItemQ = 2;
};
}
}
并像这样使用它:
var options = OptionsStruct.GetDefault();
options.ItemA = 3;
SetOptions(options);
如果你的属性数量不是太多,你还可以使用带有可选参数的构造函数:
public struct OptionsStruct
{
public int ItemA { get; set; }
public int ItemQ { get; set; }
public OptionsStruct(int itemA = 2, int itemQ = 2)
{
ItemA = itemA;
ItemQ = itemQ;
}
}
但只有当你给它至少一个参数时才会调用它:
var options1 = new OptionsStruct(); // The "default" constructor is called, so everythng will be 0.
Console.WriteLine(options1.ItemA); // 0
Console.WriteLine(options1.ItemQ); // 0
var options2 = new OptionsStruct(3); // Everything works as expected.
Console.WriteLine(options1.ItemA); // 3
Console.WriteLine(options1.ItemQ); // 2