C# 9 新特性——record的相关总结

C# 9 新特性——record的相关总结

引言

C# 9.0 版本带来了一些非常实用的新特性,其中最引人注目的莫过于record。这是一种新型的数据类型,专门用于表示“记录”数据,以及可以设置许多与属性相关的缺省值和模式匹配操作,使用起来非常方便。

本文主要讲解 C# 9 新特性中 record 的一些基础知识、语法、应用场景等内容。

C# 9.0 新特性 —— record

record 是 C#9.0 新加入的一种新类型,是 struct 的一种变种,主要用于表示不可变的数据。

record 和 struct 和 class 一样,都是定义一种新的数据集合,但它有一些特殊的属性:

  • record 可以声明为不可变的类型(只读)
  • record 的相等比较是值类型比较,而非引用类型比较。
  • record 的基本构造函数是带参数的,它自己有很多构造函数。
  • 在模式匹配(pattern matching)分支语句中,record 有额外的选项。

如果您在使用 .NET Core 3.1 和 C# 9.0,则需要将以下行添加到 csproj 文件中,以启用 C# 9.0。

<PropertyGroup>
  <LangVersion>9.0</LangVersion>
</PropertyGroup>

类 vs record

假设我们要编写一个应用程序,用于存储和显示一些长方形信息。我们可以定义 Rectangle 类,其中包含 Width 和 Height 属性。以下是该代码的示例:

public class Rectangle {
  public int Width { get; set; }
  public int Height { get; set; }

  public Rectangle(int width, int height) {
    Width = width;
    Height = height;
  }
}

此时,我们可以使用以下代码创建一个 Rectangle 对象:

Rectangle rect = new Rectangle(100, 150);

也可以更改 rect 的 Width 和 Height 属性:

rect.Width = 150;

但是,Rectangle 类有一个问题,那就是它是可变的,对象状态可以在代码中更改。换句话说,我们可以在程序的某个地方,修改 Width 和 Height 属性的值,这会导致 Rectangle 类的可变性,这在我们不希望修改某个对象状态时可能会导致问题。

为了解决这个问题,我们可以将 Rectangle 类转换为 record。

public record Rectangle(int Width, int Height);

这里我们定义了一个具有 Width 和 Height 两个属性的 record。这个属性不能更改,它是一个不可变的类型。这是因为我们仅仅可以从构造函数获取 record 的值,所以不允许使用默认的 setter 方法来更改 record 中的属性值。

定义 record 后,我们可以使用以下代码创建 Rectangle 对象。

Rectangle rect = new Rectangle(100, 150);

我们可以在代码的任何地方使用“新实例化”创建 Rectangle 对象,并且在声明后,它的属性名称和值都不能被修改。这意味着,rect 现在是一个不可变对象,在代码的任何其它地方,如果未经允许改变其状态,将不会影响到该对象。

record 类型语法介绍

record 类型的语法有五种。

1. 默认 record 类型

默认 record 类型类似如下代码。

public record Person {
  public string FirstName { get; init; }
  public string LastName { get; init; }
  public int Age { get; init; }
}

这里我们定义了一个名为 Person 的 record。Person 有 3 个属性:FirstName、LastName 和 Age。

1.1. init 属性

record 中的属性,可以使用 readonly 属性或可写的 init 属性设置只读(不可修改)状态。init 只能在构造函数中分配。

2. 可以增加一个 positional record 类型

位置记录的定义方式类似如下代码:

public record Person(string FirstName, string LastName, int Age);

3. 可以扩展 record 类型:

扩展 record 类型的方法类似如下

public record Person : ICloneable {
  public string FirstName { get; init; }
  public string LastName { get; init; }
  public int Age { get; init; }

  public object Clone() {
    return this.MemberwiseClone();
  }
}

这里,Person 继承了 ICloneable 接口,并实现了该接口的 Clone() 方法。

4. record 类型可以是泛型:

定义泛型 record 类型的方法如下:

public record Person<T>(string FirstName, string LastName, T Age);

5. record 类型可以定义私有构造函数和其他类成员:

public record Student {
  public string FirstName { get; init; }
  public string LastName { get; init; }
  public int Age { get; init; }

  private int _score;

  public Student(string firstName, string lastName, int age, int score) {
    FirstName = firstName;
    LastName = lastName;
    Age = age;
    _score = score; // 带有非默认的构造函数
  }
}

with表达式

使用 with 表达式来创建一个新的 record 对象,可以保留原始 record 对象的值,并根据需要更改一些属性。

以下是一个示例:

public record Person {
  public string FirstName { get; init; }
  public string LastName { get; init; }
  public int Age { get; init; }
}

Person person = new Person { FirstName = "Tony", LastName = "Stark", Age = 45 };

Person person2 = person with { LastName = "王" };

在这个例子中,我们定义了一个名为 Person 的 record 类型。我们创建了一个名为 person 的 Person 对象,FirstName、LastName 和 Age 分别被初始化为 "Tony"、"Stark" 和 45。

我们使用 with 表达式创建了另一个名为 person2 的 Person 对象,在这个新对象中我们仅更改了 LastName 属性。

记录变量 Person2 其余的值(即 FirstName 和 Age)来自 person。因此,person2 与 person 具有相同的值的属性,但有不同的 LastName 值。记住,这不会更改原始 record 的值,它只会创建一个新的 record 对象。

record struct

record struct 类似对结构体的定义,仅具有存储字段,而没有方法。

public record struct Foo {
    private int _value;

    public Foo(int value) {
        _value = value;
    }

    public int DoubleValue => _value * 2;
}

总结

Record 是一种非常有用的类型,在 C# 9.0 版本中,提供了一些很好的优化。使用 Record,我们主要可以得到以下两个好处。

其一,在读取你输入的对象时,如果其中的数据结构类似于 Record,那么就可以非常方便地为其设置默认值和构造函数,将同样类型的数据作为一个 Record 类型来处理。

其二,使用 Record 类型,我们可以实现一些非常高效的编程。这是因为 Record 可以通过引用传递而不是 clone。如上所述,不能更改 Record 中属性的值,而且引用传递将有助于避免发生不必要的克隆操作。因此,使用 Record 允许我们将一些应该不变的数据类型做成不可变的对象。

以上就是 C# 9 中 Record 的相关总结。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# 9 新特性——record的相关总结 - Python技术站

(0)
上一篇 2023年6月7日
下一篇 2023年6月7日

相关文章

  • asp.net core 获取 MacAddress 地址方法示例

    ASP.NET Core获取MacAddress地址方法示例攻略 在ASP.NET Core应用程序中,我们可能需要获取计算机的MacAddress地址。本攻略将介绍如何使用C#代码获取MacAddress地址。 步骤 以下是获取MacAddress地址的步骤: 引用System.Net.NetworkInformation命名空间。 使用System.Ne…

    C# 2023年5月17日
    00
  • C#实现闹钟AlarmClock实例代码

    下面是详细讲解“C#实现闹钟AlarmClock实例代码”的完整攻略: 1. 确定需求 我们要实现一个简单的闹钟程序,具有设置闹钟时间、开启闹钟、关闭闹钟等功能。 2. 创建C#控制台应用程序 打开Visual Studio,选择“新建项目”,选择“Visual C#”类型,“控制台应用程序”模板,输入项目名称,点击“创建”按钮。这样就创建了一个空白的控制台…

    C# 2023年6月6日
    00
  • C#编写的Base64加密和解密类

    基于C#语言的编写Base64加密和解密类可遵循以下步骤: 第一步:引用命名空间 using System; using System.Text; 第二步:定义加密和解密方法 public static string Base64Encode(string str) { byte[] bytes = Encoding.UTF8.GetBytes(str); …

    C# 2023年6月7日
    00
  • C# StringBuilder.Remove()方法:

    StringBuilder.Remove() 方法用于删除字符串中的一段指定长度的字符,它返回一个新的 StringBuilder 对象,表示经过删除后的字符串。 使用方法: StringBuilder.Remove(int startIndex, int length); 参数说明: startIndex:开始删除的位置的索引。 length:删除的长度。…

    C# 2023年4月19日
    00
  • html5实现的便签特效(实战分享)

    HTML5提供了许多新的特性,可以实现各种各样的特效。本攻略将介绍如何使用HTML5实现便签特效。以下是实现便签特效的完整攻略。 实现便签特效 以下是使用HTML5实现便签特效的步骤: 步骤1:创建HTML文件 在HTML文件中添加以下代码: <!DOCTYPE html> <html> <head> <meta c…

    C# 2023年5月15日
    00
  • C# 执行CMD命令并接收返回结果的操作方式

    下面我会详细讲解如何在C#中执行CMD命令并接收返回结果的操作方式,步骤如下: 第一步:引入命名空间和创建Process对象 using System.Diagnostics; 通过引入System.Diagnostics命名空间,我们可以使用Process类来执行CMD命令并接收返回结果。我们需要先创建一个Process对象来执行CMD命令,以便可以设置P…

    C# 2023年5月15日
    00
  • ASP.NET加密解密算法分享

    ASP.NET加密解密算法分享 在ASP.NET开发中,我们经常使用加密解密算法对用户数据等敏感信息进行安全保护。本文将介绍常见的ASP.NET加密解密算法示例,涵盖对称加密算法、非对称加密算法以及哈希算法等多种加密手段。 对称加密算法 对称加密算法是一种基于密钥的加密方式,同一把密钥可以同时用于加密和解密。在ASP.NET中,常用的对称加密算法包括DES、…

    C# 2023年6月3日
    00
  • 如何将Winform移植到.NET Core 3.0

    将Winform移植到.NET Core 3.0的完整攻略如下: 确认.NET Core 3.0 SDK已安装 在开始移植之前,需要确认已安装.NET Core 3.0 SDK。您可以在命令行中运行以下命令来检查是否已安装.NET Core 3.0 SDK: dotnet –version 如果输出的版本号为3.0或更高版本,则.NET Core 3.0 …

    C# 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部