C# record简洁的代码缓解GC压力
简介
record 是一种特殊的引用类型,它具备不可变性和值语义(value semantics)。record 提供了简洁的声明方式,自动生成常见的样板代码,并实现了一系列便捷特性。它可以继承其他类或实现接口。它还可以应用特性,就像 class 一样。
public record Product(int Id, string Name, decimal Price);
特性
- 不可变性:默认属性是只读的(init 访问器)。
- 值比较:基于值比较属性,而不是引用比较。
- with 表达式:可以通过 with 表达式创建现有对象的副本并修改部分属性。
- 内置样板代码:自动生成 Equals、GetHashCode 和 ToString 方法。
优势
代码简化
使用 record 可以直接生成 Equals、GetHashCode、ToString、解构器和 with 方法。以 Product 为例:
public record Product(int Id, string Name, decimal Price);
等同于传统class
public class Product
{
public int Id { get; }
public string Name { get; }
public decimal Price { get; }
public Product(int id, string name, decimal price)
{
Id = id;
Name = name;
Price = price;
}
public override bool Equals(object obj)
{
if (obj is not Product other)
return false;
return Id == other.Id && Name == other.Name && Price == other.Price;
}
public override int GetHashCode() => HashCode.Combine(Id, Name, Price);
public override string ToString() => $"Product {{ Id = {Id}, Name = {Name}, Price = {Price} }}";
}
缓解 GC 压力
使用 record 可以缓解 GC 压力,特别是在多线程环境和数据传输对象场景中。
不可变性与线程安全
- record 类型默认不可变(通过 init 访问器),因此它们在多线程环境中天然具有线程安全性,不需要锁或同步机制即可共享。这减少了锁的使用和线程争用,降低了 CPU 使用率和上下文切换开销。
减少内存分配
- 不可变对象一旦创建就不会改变,因此可以长期保持在内存中。这减少了频繁修改状态导致的内存分配和垃圾回收压力。
结合值对象的轻量级特性
- 通过 record struct(C# 10.0 引入)实现的值对象结合了不可变性和轻量级特性,减少了内存分配和传递开销。
with 表达式简化对象创建
record 类型的 with 表达式允许从现有对象派生新的对象实例并修改部分属性。
var originalProduct = new Product(1, "Laptop", 999.99m);
var updatedProduct = originalProduct with { Price = 899.99m };
Console.WriteLine(originalProduct); // Product { Id = 1, Name = Laptop, Price = 999.99 }
Console.WriteLine(updatedProduct); // Product { Id = 1, Name = Laptop, Price = 899.99 }