.NET 帮助

C#记录与类(开发人员如何使用)

发布 2024年八月11日
分享:

在 C# 的世界里,有两种主要结构被用来对数据进行建模和封装: 记录两者都作为引用类型,但在其预期用途、行为以及处理相等性方面存在很大差异。本指南将剖析这些差异,提供清晰的示例和实际用途,以帮助开发人员选择适合其需求的结构。我们还将了解 IronPDF 库.

C#类:基础知识

类一直是C#中面向对象编程的基石,旨在封装数据和行为。它们是引用类型,这意味着具有相同值的两个类实例被视为两个独立的对象。在比较两个类实例时,这一区别至关重要;默认比较是基于引用的,而不是基于值的。

public class Person
{
    public int Id { get; set; }
    public string FullName { get; set; }
}
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 Class
VB   C#

在上面的例子中,Person 是一个具有 IdFullName 属性的类。即使两个 Person 实例具有完全相同的 IdFullName 值,默认情况下它们也不会被视为相同,因为它们在内存中是两个不同的引用。

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)
VB   C#

在上例中,记录定义更加简洁,减少了模板代码。记录自动支持无损突变和基于值的比较。具有相同值的两个记录实例被认为是相等的,这与值的语义是一致的。

实际用途:何时使用记录与类

在类和记录或 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 Class
VB   C#

记录实施:

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)
VB   C#

请注意记录实现的简洁性。记录会自动为基于值的等价生成构造函数、属性和方法。

理解等同性: 引用 vs 值

C# 中类和记录类型之间的核心区别确实在于它们如何处理等同性:

  1. 类默认使用引用等同性,这意味着如果两个实例指向相同的内存地址,它们就是相等的。

  2. 记录默认使用值等同性,认为如果两个实例的属性具有相同的值,它们就是相等的。

引用等同性示例 (班级)

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: False
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: False
Public 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
VB   C#

类的两个实例即使具有相同的属性值,也不会被视为相等,因为它们在内存中是不同的对象。

值相等示例

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: True
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: 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
VB   C#

默认情况下,具有相同属性值的两个记录实例被视为相等。

高级功能:记录

记录具有多种高级功能,可满足对不可变数据结构和基于值的平等性的需求。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" }
VB   C#

这一功能在处理不可变数据结构时非常方便,因为它提供了一种 "修改 "实例而不改变原始数据的方法。

IronPDF 库简介

IronPDF 网页

IronPDF 是一款面向 .NET 开发人员的 PDF 库,为直接在 .NET 应用程序中创建、编辑和管理 PDF 文档提供了全面的解决方案。它简化了 PDF 生成过程,允许开发人员 转换 HTML, CSS, JavaScript 和图像转换为 PDF。IronPDF 支持多种 .NET 框架和项目类型,包括网络、桌面和控制台应用程序,跨多个操作系统如 Windows、Linux 和 macOS。

除了创建 PDF,IronPDF 还提供编辑 PDF、设置属性和安全性、处理 PDF 表单和提取内容的功能。它专为寻求可靠工具以将 PDF 功能集成到 .NET 项目中的开发人员而设计。

代码示例

使用 IronPDF 在 C# 中创建 PDF 可通过类和记录两种方法实现。下面是两种方法生成简单 PDF 文档的示例。C# 中类和记录的主要区别在于它们的预期用途:类默认是可变的,设计用于传统的面向对象编程,而记录是不可变的,设计用于基于值的编程,使它们成为数据建模的理想选择。

使用类

在本例中,我们将定义一个 PdfGenerator 类,该类包含一个从给定 HTML 字符串创建 PDF 的方法。

using IronPdf;

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";

        var generator = new PdfGenerator("<h1>Hello, World from Class!</h1>");
        generator.GeneratePdf("ClassExample.pdf");
    }
}
using IronPdf;

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";

        var generator = new PdfGenerator("<h1>Hello, World from Class!</h1>");
        generator.GeneratePdf("ClassExample.pdf");
    }
}
Imports IronPdf

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"

		Dim generator = New PdfGenerator("<h1>Hello, World from Class!</h1>")
		generator.GeneratePdf("ClassExample.pdf")
	End Sub
End Class
VB   C#

输出:

课堂示例输出的PDF

使用记录

相比之下,C# 中的记录在初始化后是不可变的。下面是如何利用 with-expression 来修改记录,从而获得类似的结果,with-expression 本质上是返回一个带有所需更改的新记录实例。

using IronPdf;

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";

        var recordGenerator = new PdfGeneratorRecord("<h1>Hello, World from Record!</h1>");
        recordGenerator.GeneratePdf("RecordExample.pdf");
    }
}
using IronPdf;

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";

        var recordGenerator = new PdfGeneratorRecord("<h1>Hello, World from Record!</h1>");
        recordGenerator.GeneratePdf("RecordExample.pdf");
    }
}
Imports IronPdf

'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"

		Dim recordGenerator = New PdfGeneratorRecord("<h1>Hello, World from Record!</h1>")
		recordGenerator.GeneratePdf("RecordExample.pdf")
	End Sub
End Class
VB   C#

输出:

从记录示例输出的PDF

这些示例说明了如何使用 IronPDF 通过 C# 中的类和记录生成 PDF 文件。选择使用类还是记录取决于您的具体需求:如果您需要的对象在创建后会被修改,那么类可能更合适。如果您要处理的数据在创建后不会发生变化,或者您喜欢语法上的简洁性和不变性的安全性,那么记录可能是更好的选择。

结论

IronPDF许可页面

总之,类提供了传统的面向对象功能,具有可变状态和基于引用的等价性,而记录则提供了一种现代方法来定义不可变的数据结构,具有基于值的等价性。

在选择使用类还是记录时,应根据应用程序的具体要求,考虑对不可变性的需求、数据结构的复杂性以及首选的等价比较方法等因素。 IronPDF 提供了 免费试用 对于那些希望将 PDF 功能集成到其 .NET 应用程序中的用户,许可证价格从 749 美元起。

< 前一页
C# 休眠 (开发人员如何使用)
下一步 >
MySqlclient C#(开发人员使用指南)

准备开始了吗? 版本: 2024.9 刚刚发布

免费NuGet下载 总下载量: 10,731,156 查看许可证 >