当前位置: 欣欣网 > 码农

掌握 C# 中的记录:深入了解 C# 9 的不可变性功能

2024-07-09码农

介绍

随着 C# 9 的发布,Microsoft 引入了记录,这是一种新的引用类型,可显著简化不可变数据对象的创建。记录特别适用于不可变性和值相等性至关重要的方案,例如数据传输对象 (DTO)、配置对象等。

在这篇文章中,我们将探讨 C# 9 中记录的详细信息、如何有效地使用它们,以及它们可以大大增强代码的一些高级方案。

什么是Records?

C# 9 中的记录提供了一种简洁的方法来定义具有内置值相等性的不可变数据对象。与传统类不同,记录被设计为默认不可变,这意味着它们的状态在创建后无法修改。

基本记录声明

下面是 C# 9 中记录的简单示例:

publicrecordPerson(string FirstName, string LastName);

在此示例中,是具有两个属性的记录:和 。编译器会自动为此记录生成多个成员,包括:PersonFirstNameLastName

  • 接受 和 的构造函数。FirstNameLastName

  • 和 的只读属性。FirstNameLastName

  • 位置模式匹配的解构方法。

  • 基于值的相等方法 (, )。EqualsGetHashCode

  • Immutability and With-Expressions

    记录的关键特征之一是不可变性。创建记录后,无法修改其属性。但是,您可以使用 with-expressions 创建更改某些属性的新记录:

    var person = newPerson("John", "Doe");
    var updatedPerson = person with { LastName = "Smith" };
    Console.WriteLine(person); // Output: Person { FirstName = John, LastName = Doe }
    Console.WriteLine(updatedPerson); // Output: Person { FirstName = John, LastName = Smith }

    该关键字创建记录的新实例,复制现有值并应用指定的更改。with

    Value Equality

    记录提供内置值相等,这意味着具有相同数据的两条记录被视为相等:

    var person1 = newPerson("John", "Doe");
    var person2 = newPerson("John", "Doe");
    Console.WriteLine(person1 == person2); // Output: True
    Console.WriteLine(person1.Equals(person2)); // Output: True

    此行为与类形成鲜明对比,在类中,默认情况下,相等性基于对象引用。

    Advanced Scenarios

    位置记录

    位置记录允许您使用位置参数定义记录,使代码更加简洁:

    publicrecordPoint(int X, int Y);
    var point = newPoint(1, 2);
    var (x, y) = point; // Deconstruction
    Console.WriteLine($"X: {x}, Y: {y}"); // Output: X: 1, Y: 2

    自定义记录

    虽然记录提供了许多内置功能,但您可以通过添加其他方法或覆盖现有方法来自定义它们:

    publicrecordPerson(string FirstName, string LastName)
    {
    publicstring FullName => $"{FirstName}{LastName}";
    publicoverridestringToString() => $"Person: {FullName}";
    }
    var person = newPerson("John", "Doe");
    Console.WriteLine(person); // Output: Person: John Doe

    记录和继承

    记录支持继承,允许您创建不可变类型的层次结构:

    publicrecordPerson(string FirstName, string LastName);
    publicrecordEmployee(string FirstName, string LastName, string Position) : Person(FirstName, LastName);
    var employee = newEmployee("John", "Doe", "Developer");
    Console.WriteLine(employee); // Output: Employee { FirstName = John, LastName = Doe, Position = Developer }

    非位置记录

    您还可以定义非位置记录,从而更好地控制属性初始化:

    publicrecordCar
    {
    publicstring Make { get; init; }
    publicstring Model { get; init; }
    publicCar(string make, string model)
    {
    Make = make;
    Model = model;
    }
    }
    var car = newCar("Toyota", "Corolla");
    Console.WriteLine(car); // Output: Car { Make = Toyota, Model = Corolla }

    记录中的可变性

    虽然默认情况下记录是不可变的,但如有必要,您可以定义可变记录。但是,通常不鼓励这样做,因为它违背了记录的主要设计原则:

    publicrecordMutablePerson
    {
    publicstring FirstName { get; set; }
    publicstring LastName { get; set; }
    }

    实际应用

    记录在不可变性和值相等很重要的方案中特别有用。以下是一些实际应用:

    数据传输对象 (DTO)
    记录是 DTO 的理想选择,DTO 通常需要不可变性和值相等:

    publicrecordCustomerDto(int Id, string Name, string Email);

    配置对象
    记录提供了一种方便的方法来定义配置对象,这些对象在初始化后不应更改:

    publicrecordAppConfig(string ConnectionString, int MaxRetries);

    活动溯源
    在事件源系统中,记录可用于表示不可变事件:

    publicrecordOrderPlaced(Guid OrderId, DateTime PlacedAt, decimal Amount);

    结论

    C# 9 中的记录引入了一种强大而简洁的方法来定义具有内置值相等性的不可变数据对象。通过利用记录,您可以创建更可靠和可维护的代码,尤其是在不可变性和值平等至关重要的情况下。

    无论您使用的是 DTO、配置对象还是事件源系统,记录都提供了一种在 C# 中定义数据结构的现代高效方法。采用此功能可增强您的 C# 编程技能并构建更可靠的应用程序。

    如果你喜欢我的文章,请给我一个赞!谢谢