C# Record 与 Class(开发人员如何使用)
在 C# 的世界中,主要使用两种结构来建模和封装数据:类和记录。 两者都是引用类型,但在其预期用途、行为及处理相等性方式上有显著差异。 本指南将解析这些差异,提供清晰的示例和实用用例,帮助开发人员选择适合他们需求的结构。 我们还将了解IronPDF library。
C#中的类:基础知识
类是 C# 面向对象编程的基石,旨在封装数据和行为。 它们是引用类型,这意味着具有相同值的两个类实例被视为两个独立的对象。 这种区别在比较两个类实例时至关重要; 默认比较是基于引用的,而不是基于值的。
public class Person
{
public int Id { get; set; }
public string FullName { get; set; }
}Public Class Person
Public Property Id() As Integer
Public Property FullName() As String
End ClassPublic Class Person
Public Property Id() As Integer
Public Property FullName() As String
End Class在上述示例中,Person 是一个带有 Id 和 FullName 属性的类。 即使两个 Person 实例具有相同的 Id 和 FullName 值,默认情况下它们也不会被认为是相等的,因为它们在内存中是两个不同的引用。
C#中的记录:不可变数据结构
在 C# 中引入的记录类型是为了简化不可变数据结构的创建,提供了一个更为强大的替代传统类结构的方法。 与类不同,记录提供基于值的相等性语义,使其非常适合于数据传输对象或行为较少的小型数据结构。
public record Person(int Id, string FullName);public record Person(int Id, string FullName);'INSTANT VB TODO TASK: C# 'records' are not converted by Instant VB:
'public record Person(int Id, string FullName)'INSTANT VB TODO TASK: C# 'records' are not converted by Instant VB:
'public record Person(int Id, string FullName)在上述示例中,记录定义更简洁,减少了样板代码。 记录自动支持无损变更和基于值的比较。 具有相同值的两条记录实例被认为是相等的,与值语义对齐。
实用用例:何时使用记录还是类
在 C# 中选择使用类、记录或其他数据结构,取决于您所建模数据的复杂性以及应用程序所需的行为。 类专为复杂的数据结构设计,支持行为(方法)并允许根据需要修改实例。 而记录是简单数据结构的完美典范,设计时具有不可变的特性和基于值的相等性,非常适合创建后保持不变的数据。
当您的数据结构需要封装数据和行为或者您需要在创建后操纵数据时,类是理想的。 这种灵活性使类成为大多数传统面向对象编程场景以及构建复杂数据结构的首选。
在数据不可变性至关重要或处理作为数据容器的简单数据结构时,记录更加出色。 它们内置的基于值的相等性和简洁的语法使它们成为数据传输对象或值对象的优秀选择。
值类型和引用类型
理解 C# 中值类型和引用类型的区别至关重要。 类是引用类型,这意味着变量持有指向内存中实际数据的引用。 这种特性导致了默认的基于引用的相等性比较。
记录虽然也是引用类型,但通过其内置的基于值的相等性模拟值语义,使其在比较时表现得有点像值类型。
代码示例:实现类和记录
让我们实现一个类和一个记录,以突出语法和行为上的差异。
类实现:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public Product(int id, string name)
{
Id = id;
Name = name;
}
}public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public Product(int id, string name)
{
Id = id;
Name = name;
}
}Public Class Product
Public Property Id() As Integer
Public Property Name() As String
Public Sub New(ByVal id As Integer, ByVal name As String)
Me.Id = id
Me.Name = name
End Sub
End ClassPublic Class Product
Public Property Id() As Integer
Public Property Name() As String
Public Sub New(ByVal id As Integer, ByVal name As String)
Me.Id = id
Me.Name = name
End Sub
End Class记录实现:
public record Product(int Id, string Name);public record Product(int Id, string Name);'INSTANT VB TODO TASK: C# 'records' are not converted by Instant VB:
'public record Product(int Id, string Name)'INSTANT VB TODO TASK: C# 'records' are not converted by Instant VB:
'public record Product(int Id, string Name)请注意记录实现的简洁性和简易性。 记录会自动生成构造函数、属性和用于基于值相等的方法。
理解相等性:引用 vs. 值
C# 中类和记录类型之间的核心区别确实在于它们如何处理相等性:
-
类默认使用引用相等性,这意味着如果两个实例指向相同的内存位置,它们就是相等的。
-
记录默认使用值相等性,当属性具有相同的值时,认为两个实例是相等的。
引用相等性示例(类)
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
var classInstance1 = new Person { Id = 1, Name = "Iron Software" };
var classInstance2 = new Person { Id = 1, Name = "Iron Software" };
Console.WriteLine(classInstance1 == classInstance2); // Outputs: Falsepublic class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
var classInstance1 = new Person { Id = 1, Name = "Iron Software" };
var classInstance2 = new Person { Id = 1, Name = "Iron Software" };
Console.WriteLine(classInstance1 == classInstance2); // Outputs: FalsePublic Class Person
Public Property Id() As Integer
Public Property Name() As String
End Class
Private classInstance1 = New Person With {
.Id = 1,
.Name = "Iron Software"
}
Private classInstance2 = New Person With {
.Id = 1,
.Name = "Iron Software"
}
Console.WriteLine(classInstance1 = classInstance2) ' Outputs: FalsePublic Class Person
Public Property Id() As Integer
Public Property Name() As String
End Class
Private classInstance1 = New Person With {
.Id = 1,
.Name = "Iron Software"
}
Private classInstance2 = New Person With {
.Id = 1,
.Name = "Iron Software"
}
Console.WriteLine(classInstance1 = classInstance2) ' Outputs: False具有相同属性值的两个类实例不会被认为是相等的,因为它们在内存中是不同的对象。
值相等性示例
public record Person(int Id, string Name);
var recordInstance1 = new Person(1, "Iron Software");
var recordInstance2 = new Person(1, "Iron Software");
Console.WriteLine(recordInstance1 == recordInstance2); // Outputs: Truepublic record Person(int Id, string Name);
var recordInstance1 = new Person(1, "Iron Software");
var recordInstance2 = new Person(1, "Iron Software");
Console.WriteLine(recordInstance1 == recordInstance2); // Outputs: True'INSTANT VB TODO TASK: C# 'records' are not converted by Instant VB:
'public record Person(int Id, string Name)
Private recordInstance1 = New Person(1, "Iron Software")
Private recordInstance2 = New Person(1, "Iron Software")
Console.WriteLine(recordInstance1 = recordInstance2) ' Outputs: True'INSTANT VB TODO TASK: C# 'records' are not converted by Instant VB:
'public record Person(int Id, string Name)
Private recordInstance1 = New Person(1, "Iron Software")
Private recordInstance2 = New Person(1, "Iron Software")
Console.WriteLine(recordInstance1 = recordInstance2) ' Outputs: True具有相同属性值的两个记录实例默认被认为是相等的。
高级功能:记录
记录具有若干高级功能,以满足不可变数据结构和基于值相等性的需求。 with 表达式允许通过复制现有记录并修改某些属性来创建新的记录实例,展示了无损变更。
使用记录进行无损变更:
var originalRecord = new Person(1, "Doe");
var modifiedRecord = originalRecord with { Name = "Iron Developer" };var originalRecord = new Person(1, "Doe");
var modifiedRecord = originalRecord with { Name = "Iron Developer" };Dim originalRecord = New Person(1, "Doe")
'INSTANT VB TODO TASK: C# 'with expressions' are not converted by Instant VB:
'var modifiedRecord = originalRecord with { Name = "Iron Developer" }Dim originalRecord = New Person(1, "Doe")
'INSTANT VB TODO TASK: C# 'with expressions' are not converted by Instant VB:
'var modifiedRecord = originalRecord with { Name = "Iron Developer" }此功能在使用不可变数据结构时非常方便,因为它提供了一种"修改"实例而不更改原始数据的方法。
IronPDF库简介

IronPDF 是一个为 .NET 开发人员提供的 PDF 库,提供了在 .NET 应用程序中直接创建、编辑和管理 PDF 文档的全面解决方案。 通过允许开发人员将 HTML 转换为 PDF、CSS、JavaScript 和图像简化了 PDF 生成过程。 IronPDF 支持多种 .NET Framework和项目类型,包括 Web、桌面和控制台应用程序,跨多个操作系统如 Windows、Linux 和 macOS。
除了创建 PDF,IronPDF 还提供编辑 PDF、设置属性和安全性、处理 PDF 表单和提取内容的功能。 它旨在满足希望将 PDF 功能集成到其 .NET 项目的开发人员的需求。
代码示例
using IronPDF 在 C# 中创建 PDF 可以通过类和记录来实现。 以下是生成简单 PDF 文档的两种方法的示例。 C# 中类和记录的主要区别在于它们的预期用途:类默认是可变的,设计用于传统的面向对象编程,而记录是不可变的,设计用于基于值编程,使其非常适合于数据建模。
使用类
在此示例中,我们将定义一个包含从给定 HTML 字符串创建 PDF 方法的PdfGenerator 类。
using IronPdf;
using System;
public class PdfGenerator
{
public string HtmlContent { get; set; }
public PdfGenerator(string htmlContent)
{
HtmlContent = htmlContent;
}
public void GeneratePdf(string filePath)
{
var renderer = new ChromePdfRenderer();
var pdfDocument = renderer.RenderHtmlAsPdf(HtmlContent);
pdfDocument.SaveAs(filePath);
}
}
class Program
{
public static void Main(string[] args)
{
License.LicenseKey = "License-Key"; // Set your license key here
var generator = new PdfGenerator("<h1>Hello, World from Class!</h1>");
generator.GeneratePdf("ClassExample.pdf");
}
}using IronPdf;
using System;
public class PdfGenerator
{
public string HtmlContent { get; set; }
public PdfGenerator(string htmlContent)
{
HtmlContent = htmlContent;
}
public void GeneratePdf(string filePath)
{
var renderer = new ChromePdfRenderer();
var pdfDocument = renderer.RenderHtmlAsPdf(HtmlContent);
pdfDocument.SaveAs(filePath);
}
}
class Program
{
public static void Main(string[] args)
{
License.LicenseKey = "License-Key"; // Set your license key here
var generator = new PdfGenerator("<h1>Hello, World from Class!</h1>");
generator.GeneratePdf("ClassExample.pdf");
}
}Imports IronPdf
Imports System
Public Class PdfGenerator
Public Property HtmlContent() As String
Public Sub New(ByVal htmlContent As String)
Me.HtmlContent = htmlContent
End Sub
Public Sub GeneratePdf(ByVal filePath As String)
Dim renderer = New ChromePdfRenderer()
Dim pdfDocument = renderer.RenderHtmlAsPdf(HtmlContent)
pdfDocument.SaveAs(filePath)
End Sub
End Class
Friend Class Program
Public Shared Sub Main(ByVal args() As String)
License.LicenseKey = "License-Key" ' Set your license key here
Dim generator = New PdfGenerator("<h1>Hello, World from Class!</h1>")
generator.GeneratePdf("ClassExample.pdf")
End Sub
End ClassImports IronPdf
Imports System
Public Class PdfGenerator
Public Property HtmlContent() As String
Public Sub New(ByVal htmlContent As String)
Me.HtmlContent = htmlContent
End Sub
Public Sub GeneratePdf(ByVal filePath As String)
Dim renderer = New ChromePdfRenderer()
Dim pdfDocument = renderer.RenderHtmlAsPdf(HtmlContent)
pdfDocument.SaveAs(filePath)
End Sub
End Class
Friend Class Program
Public Shared Sub Main(ByVal args() As String)
License.LicenseKey = "License-Key" ' Set your license key here
Dim generator = New PdfGenerator("<h1>Hello, World from Class!</h1>")
generator.GeneratePdf("ClassExample.pdf")
End Sub
End Class输出:

使用记录
相比之下,C# 中的记录在初始化后是不可变的。 以下是如何使用记录来实现类似的结果,利用with表达式进行修改,实质上是返回一个包含所需更改的新记录实例。
using IronPdf;
using System;
public record PdfGeneratorRecord(string HtmlContent)
{
public void GeneratePdf(string filePath)
{
var renderer = new ChromePdfRenderer();
var pdfDocument = renderer.RenderHtmlAsPdf(this.HtmlContent);
pdfDocument.SaveAs(filePath);
}
}
class Program
{
public static void Main(string[] args)
{
License.LicenseKey = "License-Key"; // Set your license key here
var recordGenerator = new PdfGeneratorRecord("<h1>Hello, World from Record!</h1>");
recordGenerator.GeneratePdf("RecordExample.pdf");
}
}using IronPdf;
using System;
public record PdfGeneratorRecord(string HtmlContent)
{
public void GeneratePdf(string filePath)
{
var renderer = new ChromePdfRenderer();
var pdfDocument = renderer.RenderHtmlAsPdf(this.HtmlContent);
pdfDocument.SaveAs(filePath);
}
}
class Program
{
public static void Main(string[] args)
{
License.LicenseKey = "License-Key"; // Set your license key here
var recordGenerator = new PdfGeneratorRecord("<h1>Hello, World from Record!</h1>");
recordGenerator.GeneratePdf("RecordExample.pdf");
}
}Imports IronPdf
Imports System
'INSTANT VB TODO TASK: C# 'records' are not converted by Instant VB:
'public record PdfGeneratorRecord(string HtmlContent)
'{
' public void GeneratePdf(string filePath)
' {
' var renderer = New ChromePdfRenderer();
' var pdfDocument = renderer.RenderHtmlAsPdf(Me.HtmlContent);
' pdfDocument.SaveAs(filePath);
' }
'}
Friend Class Program
Public Shared Sub Main(ByVal args() As String)
License.LicenseKey = "License-Key" ' Set your license key here
Dim recordGenerator = New PdfGeneratorRecord("<h1>Hello, World from Record!</h1>")
recordGenerator.GeneratePdf("RecordExample.pdf")
End Sub
End ClassImports IronPdf
Imports System
'INSTANT VB TODO TASK: C# 'records' are not converted by Instant VB:
'public record PdfGeneratorRecord(string HtmlContent)
'{
' public void GeneratePdf(string filePath)
' {
' var renderer = New ChromePdfRenderer();
' var pdfDocument = renderer.RenderHtmlAsPdf(Me.HtmlContent);
' pdfDocument.SaveAs(filePath);
' }
'}
Friend Class Program
Public Shared Sub Main(ByVal args() As String)
License.LicenseKey = "License-Key" ' Set your license key here
Dim recordGenerator = New PdfGeneratorRecord("<h1>Hello, World from Record!</h1>")
recordGenerator.GeneratePdf("RecordExample.pdf")
End Sub
End Class输出:

这些示例演示了如何使用 IronPDF 在 C# 中通过类和记录生成 PDF 文件。 选择使用类还是记录取决于您的具体需求:如果您需要在创建后修改的对象,类可能更合适。 如果您处理的是创建后不应更改的数据,或者您欣赏不可变性的语法简洁性和安全性,记录可能是更好的选择。
结论
总之,类提供传统的面向对象功能,具有可变状态和基于引用的相等性,而记录提供现代方法来定义具有基于值相等性的不可变数据结构。
在使用类还是记录之间进行选择时,应根据应用程序的具体要求进行指导,考虑不可变性的需要、数据结构的复杂性以及首选的相等比较方法。 探索IronPDF的免费试用,适合希望将PDF功能集成到.NET应用的用户,许可证从$999起。
Jacob Mellor 是 Iron Software 的首席技术官,也是一位开创 C# PDF 技术的有远见的工程师。作为 Iron Software 核心代码库的原始开发者,他从公司成立之初就开始塑造公司的产品架构,与首席执行官 Cameron Rimington 一起将公司转变为一家拥有 50 多名员工的公司,为 NASA、特斯拉和全球政府机构提供服务。