淡若轻风

博客园 首页 新随笔 联系 订阅 管理

在C#中,with 关键字主要用于记录类型 (record types),引入于 C# 9.0,用于创建基于现有对象的非破坏性(immutable)副本

当使用 with 关键字时,可以创建一个新的对象,仅修改指定的属性值,而其他属性保持不变


with 关键字的使用示例

1. 适用于 record 类型

record 类型是一种特殊的数据结构,默认是**不可变(immutable)**的,使用 with 关键字可以方便地创建对象的新实例。

public record Person(string Name, int Age);
var person1 = new Person("Alice", 30);  //  使用 `with` 关键字创建副本并修改 Age
var person2 = person1 with { Age = 35 };
 
 
Console.WriteLine(person1); // 输出: Person { Name = Alice, Age = 30 }
Console.WriteLine(person2); // 输出: Person { Name = Alice, Age = 35 }

解释:

  • person1 是一个不可变的 record 实例。
  • with 关键字允许创建新的 person2,仅更改 Age 属性,而不改变 Name 属性。
  • record 类型默认提供值相等性(value equality),因此 person1person2 的比较将基于其字段值,而非引用。

2. init 关键字配合使用

在 C# 9.0 及以上,init 访问器允许对象在初始化后保持不可变,with 可用于创建新的副本:

public record Car
{
  public string Brand
  {
    get;
    init;
  }
  public string Model
  {
    get;
    init;
  }
}
var car1 = new Car { Brand = "Toyota", Model = "Corolla" };  // 创建副本并修改 Model
var car2 = car1 with { Model = "Camry" };
Console.WriteLine(car1);  // 输出: Car { Brand = Toyota, Model = Corolla }
Console.WriteLine(car2);  // 输出: Car { Brand = Toyota, Model = Camry }

3. 适用于具名属性的 record

可以使用 with 对复杂的 record 对象进行修改:

public record Address(string Street, string City);
public record Employee(string Name, Address Address);
var emp1 = new Employee("John", new Address("123 St", "NYC")); // 修改 Address 内部字段
var emp2 = emp1 with
{
  Address = emp1.Address with
  {
     City = "LA"
  }
};
Console.WriteLine(emp1); // 输出: Employee { Name = John, Address = Address { Street = 123 St, City = NYC } }
Console.WriteLine(emp2); // 输出: Employee { Name = John, Address = Address { Street = 123 St, City = LA } }

限制与注意事项

  1. 仅适用于 record 类型:

    • with 关键字不适用于普通的 classstruct
    • 若需类似功能,可手动实现拷贝构造函数。
  2. 不会修改原对象(不可变性):

    • with 关键字创建的是副本,不会影响原始对象。
  3. 深度嵌套需要手动处理:

    • 如果 record 内部包含复杂对象,修改时需要分别使用 with 语法。

C# 12 新增:匿名对象支持 with

在 C# 12 中,with 关键字可以用于匿名类型,提供类似功能:

var person = new
{
  Name = "Alice",
  Age = 30
};
var updatedPerson = person with
{
  Age = 35
};
Console.WriteLine(updatedPerson);  // 输出: { Name = Alice, Age = 35 }

 

posted on 2025-01-24 01:04  淡若轻风  阅读(535)  评论(0)    收藏  举报