C#10新特性之structs的改进

C# 10 为 structs 引入了功能,可在 structs (结构)和类之间提供更好的奇偶性。这些新功能包括无参数构造函数、字段初始值设定项、记录结构和 with 表达式。

01 无参数结构构造函数和字段初始值设定项

在 C# 10 之前,每个结构都有一个隐式的公共无参数构造函数,该构造函数将结构的字段设置为默认值。在结构上创建无参数构造函数是错误的。.

从 C# 10 开始,您可以包含自己的无参数结构构造函数。如果您不提供,则将提供隐式无参数构造函数以将所有字段设置为默认值。您在结构中创建的无参数构造函数必须是公共的并且不能是部分的:

public struct Address
{
    public Address()
    {
        City = "<unknown>";
    }
    public string City { get; init; }
}

您可以如上所述在无参数构造函数中初始化字段,也可以通过字段或属性初始化程序初始化它们:

public struct Address
{
    public string City { get; init; } = "<unknown>";
}

通过默认创建或作为数组分配的一部分创建的结构会忽略显式无参数构造函数,并始终将结构成员设置为其默认值。有关结构中无参数构造函数的更多信息,请参阅结构类型。

02 Record structs

从 C# 10 开始,现在可以使用 record struct 定义 record。这些类似于 C# 9 中引入的record 类:

public record struct Person
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
}

您可以继续使用 record 定义记录类,也可以使用 record 类来清楚地说明。

结构已经具有值相等——当你比较它们时,它是按值。记录结构添加 IEquatable<T> 支持和 == 运算符。记录结构提供 IEquatable<T> 的自定义实现以避免反射的性能问题,并且它们包括记录功能,如 ToString() 覆盖。

记录结构可以是位置的,主构造函数隐式声明公共成员:

public record struct Person(string FirstName, string LastName);

主构造函数的参数成为记录结构的公共自动实现属性。与 record 类不同,隐式创建的属性是读/写的。这使得将元组转换为命名类型变得更加容易。将返回类型从 (string FirstName, string LastName) 之类的元组更改为 Person 的命名类型可以清理您的代码并保证成员名称一致。声明位置记录结构很容易并保持可变语义。

如果您声明一个与主要构造函数参数同名的属性或字段,则不会合成任何自动属性并使用您的。

要创建不可变的记录结构,请将 readonly 添加到结构(就像您可以添加到任何结构一样)或将 readonly 应用于单个属性。对象初始化器是可以设置只读属性的构造阶段的一部分。这只是使用不可变记录结构的一种方法:

var person = new Person { FirstName = "Mads", LastName = "Torgersen"};
public readonly record struct Person
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
}

03 Record类中 ToString () 上的密封修饰符

记录类也得到了改进。从 C# 10 开始,ToString() 方法可以包含 seal 修饰符,这会阻止编译器为任何派生记录合成 ToString 实现。

04 结构和匿名类型的表达式

C# 10 支持所有结构的 with 表达式,包括记录结构,以及匿名类型:

var person2 = person with { LastName = "Kristensen" };

这将返回一个具有新值的新实例。您可以更新任意数量的值。您未设置的值将保留与初始实例相同的值。