对象初始化器
对象初始化器是在构造器后使用的初始值赋值补充语法。
它可以在构造器后使用花括号,依次指定成员名和赋值表达式,以逗号分隔。
对象初始化器不能为只读字段赋值,但可以对具有init访问器的属性进行赋值。
struct Point
{
public int X {
get; init; }
public int Y {
get; init; }
public static Point operator +(Point p1, Point p2)
=> new Point() {
X = p1.X + p2.X, Y = p1.Y + p2.Y };
public static Point operator -(Point p1, Point p2)
=> new Point() {
X = p1.X - p2.X, Y = p1.Y - p2.Y };
public static Point operator *(Point p, int n)
=> new Point() {
X = p.X * n, Y = p.Y * n };
public static Point operator /(Point p, int n)
=> new Point() {
X = p.X / n, Y = p.Y / n };
}
一个实例构造出来的时候运作顺序是
- 成员上赋值的初始值
- 构造器中的赋值
- 对象初始化器赋值
所以对于节省性能是没有帮助的,只能让他更简洁醒目,
以及合并为单条语句。例如如果构造的实例是要参与表达式运算的。
Point p1 = new Point {
X = 3 } + new Point {
Y = 4 };
//无参构造器使用对象初始化器,可以省略括号。
对象克隆器
对于记录类型和结构类型可以使用with
克隆目标的值,并使用对象初始化器修改一些值。
Point p2 = new Point() {
X = 3, Y = 4 };
Point p3 = p2 with {
X = 5 };
克隆的过程不会经过赋值操作(Set
和init
访问器),但之后的对象初始化器的赋值会触发赋值。
集合初始化器
实现了IEnumerable
接口并且具有Add
方法的类型(IEnumerable
接口没有要求具有Add
方法),
可以在对象初始化器中传入多个元素,这些元素会作为参数依序调用Add
方法。
System.Collections.ArrayList list = new System.Collections.ArrayList() {
1, 2, 3 };
list.Add(4);
list.Add(5);
list.Add(6);
匿名类型
匿名类是一种临时类,没有名字必须通过var
来推断类型。
和元组类似,用于打包一系列的值。但这些值是只读属性,不能更改。
匿名类型的语法是使用new关键字和对象初始化器,指定属性的名称和值。
var person = new {
Name = "Alice", Age = 20 };
所需成员
暴露的并且可更改的成员,可以添加required
进行修饰。
创建实例时会要求必须使用对象初始化器对他们进行赋值。
在派生类中,不能将这些成员进行覆写。重写这些成员时,需要沿用required
进行修饰。
Student st = new Student {
Age=20,Name="小明" };
class Student
{
public required int Age {
get; set; }
public required string Name;
}