跳至页脚内容
.NET 帮助

C# 区别联合(开发者用法)

作为使用IronPDF进行动态PDF生成的.NET开发者,你经常需要表示和管理一系列特定类型——例如各种文档数据、日志信息、用户角色或导出选项。 这就是C#区分联合的概念发挥作用的地方。

虽然C#不像F#或Rust那样原生支持区分联合,但你仍然可以有效地模拟区分联合。 在这篇博客文章中,我们将深入探讨如何在C#中定义和使用区分联合类型,展示如何在真实世界的PDF处理中应用它,并探索这种模式所提供的好处——特别是在与模式匹配配对时。

什么是C#中的区分联合?

区分联合,也称为标记联合或联合类型,允许变量从有限的可能选项集中持有一个值,其中每个选项都与唯一的案例标识符相关联。

在像F#这样的其他语言中,你可能会使用union关键字来定义它们。 C#没有提供这种特性,但开发者可以使用记录、类和switch表达式的聪明组合来模拟它们。

例如:

public abstract record PdfAction;
public record GenerateReport(string ReportName) : PdfAction;
public record LogError(string Message) : PdfAction;
public record ExportToExcel(string FilePath) : PdfAction;
public abstract record PdfAction;
public record GenerateReport(string ReportName) : PdfAction;
public record LogError(string Message) : PdfAction;
public record ExportToExcel(string FilePath) : PdfAction;
Public MustOverride ReadOnly Property PdfAction() As record
public record GenerateReport(String ReportName) : PdfAction
public record LogError(String Message) : PdfAction
public record ExportToExcel(String FilePath) : PdfAction
$vbLabelText   $csharpLabel

上面的每个记录都代表联合的一个案例。 基本的PdfAction类型是判别符。

为什么在IronPDF工作流中区分联合很重要

想象一下你正在使用IronPDF构建一个PDF报告生成器,并且需要根据用户的输入执行不同的操作——可能是生成PDF、记录错误或导出数据。

在C#中使用区分联合可以干净地表示这些选项类型,从而实现编译时安全、减少错误和更清晰的逻辑。

以下是你可能与IronPDF一起使用的方法:

void HandlePdfAction(PdfAction action)
{
    switch (action)
    {
        case GenerateReport r:
            var pdf = new IronPdf.HtmlToPdf().RenderHtmlAsPdf("<h1>" + r.ReportName + "</h1>");
            pdf.SaveAs(r.ReportName + ".pdf");
            break;
        case LogError e:
            Console.WriteLine("Logging Error: " + e.Message);
            break;
        case ExportToExcel x:
            Console.WriteLine("Exporting to Excel at " + x.FilePath);
            break;
        default:
            throw new NotSupportedException("Unknown action");
    }
}
void HandlePdfAction(PdfAction action)
{
    switch (action)
    {
        case GenerateReport r:
            var pdf = new IronPdf.HtmlToPdf().RenderHtmlAsPdf("<h1>" + r.ReportName + "</h1>");
            pdf.SaveAs(r.ReportName + ".pdf");
            break;
        case LogError e:
            Console.WriteLine("Logging Error: " + e.Message);
            break;
        case ExportToExcel x:
            Console.WriteLine("Exporting to Excel at " + x.FilePath);
            break;
        default:
            throw new NotSupportedException("Unknown action");
    }
}
Private Sub HandlePdfAction(ByVal action As PdfAction)
	Select Case action
'INSTANT VB TODO TASK: The following 'case' pattern variable is not converted by Instant VB:
'ORIGINAL LINE: case GenerateReport r:
		Case GenerateReport r
			Dim pdf = (New IronPdf.HtmlToPdf()).RenderHtmlAsPdf("<h1>" & r.ReportName & "</h1>")
			pdf.SaveAs(r.ReportName & ".pdf")
'INSTANT VB TODO TASK: The following 'case' pattern variable is not converted by Instant VB:
'ORIGINAL LINE: case LogError e:
		Case LogError e
			Console.WriteLine("Logging Error: " & e.Message)
'INSTANT VB TODO TASK: The following 'case' pattern variable is not converted by Instant VB:
'ORIGINAL LINE: case ExportToExcel x:
		Case ExportToExcel x
			Console.WriteLine("Exporting to Excel at " & x.FilePath)
		Case Else
			Throw New NotSupportedException("Unknown action")
	End Select
End Sub
$vbLabelText   $csharpLabel

这种方法保持了代码的组织和强健,并使开发者更容易在单个位置理解所有可能的选项。

在C#中模拟区分联合——结构体与记录与类

虽然C#缺少union关键字,但你可以使用以下方式模拟区分联合:

  • 记录:理想用于不可变数据,并支持干净的模式匹配。
  • :继承和引用语义更灵活。
  • 结构体:用于值类型时有用,但在处理引用类型或继承时不太灵活。

C#区分联合(对开发者的工作原理):图1 - 结构体与记录与类

如果性能和内存布局很重要——例如在高通量的PDF日志记录中,你可能需要谨慎使用结构体区分联合:

public interface IAction { }
public readonly struct SaveAction : IAction
{
    public string FileName { get; }
    public SaveAction(string fileName) => FileName = fileName;
}
public interface IAction { }
public readonly struct SaveAction : IAction
{
    public string FileName { get; }
    public SaveAction(string fileName) => FileName = fileName;
}
Public Interface IAction
End Interface
'INSTANT VB WARNING: VB has no equivalent to the C# readonly struct:
'ORIGINAL LINE: public readonly struct SaveAction : IAction
Public Structure SaveAction
	Implements IAction

	Public ReadOnly Property FileName() As String
	Public Sub New(ByVal fileName As String)
		Me.FileName = fileName
	End Sub
End Structure
$vbLabelText   $csharpLabel

注意:使用结构体会失去一些模式匹配的好处,尤其是在依赖switch表达式时。

在C#中使用区分联合的好处

采用这种软件工程模式有几个关键优势:

  • 编译时安全:在运行前会捕获到switch表达式中缺失的情况。
  • 更清晰的逻辑:更容易书写、注释和推理具有命名案例的操作。
  • 关注点分离:基于数据而非类型层次结构分离行为。
  • 重构容易:添加或移除情况变得更加直接。

与IronPDF配对时,这使得更容易管理用户输入、渲染逻辑或用不同的值管道创建动态模板。

什么时候与IronPDF一起使用区分联合

以下是该模式表现优异的一些实际场景:

  • PDF生成工作流:文档生命周期中的不同步骤(生成、保存、电子邮件)。
  • 权限模型:表示不同的用户访问级别。
  • 日志系统:为日志级别(信息、错误、调试)使用区分联合类型。
  • 单元测试:将测试操作定义为联合类型以进行可维护的逻辑树。
  • 导出选项:将输出目标如PDF、Excel、Word表示为联合实例。

C#区分联合(对开发者的工作原理):图2 - .NET应用中区分联合的常见场景

示例——处理来自UI事件的PDF动作

假设你正在捕获UI事件,并希望通过区分联合将其路由到IronPDF任务:

public abstract record UserAction;
public record GeneratePdf(string HtmlContent, string FileName) : UserAction;
public record ShowMessage(string Text) : UserAction;
public record ExitApplication() : UserAction;
void OnUserEvent(UserAction action)
{
    switch (action)
    {
        case GeneratePdf pdf:
            var renderer = new IronPdf.HtmlToPdf();
            var document = renderer.RenderHtmlAsPdf(pdf.HtmlContent);
            document.SaveAs(pdf.FileName);
            break;
        case ShowMessage msg:
            MessageBox.Show(msg.Text);
            break;
        case ExitApplication:
            Application.Exit();
            break;
    }
}
public abstract record UserAction;
public record GeneratePdf(string HtmlContent, string FileName) : UserAction;
public record ShowMessage(string Text) : UserAction;
public record ExitApplication() : UserAction;
void OnUserEvent(UserAction action)
{
    switch (action)
    {
        case GeneratePdf pdf:
            var renderer = new IronPdf.HtmlToPdf();
            var document = renderer.RenderHtmlAsPdf(pdf.HtmlContent);
            document.SaveAs(pdf.FileName);
            break;
        case ShowMessage msg:
            MessageBox.Show(msg.Text);
            break;
        case ExitApplication:
            Application.Exit();
            break;
    }
}
Public MustOverride ReadOnly Property UserAction() As record
public record GeneratePdf(String HtmlContent, String FileName) : UserAction
public record ShowMessage(String Text) : UserAction
public record ExitApplication() : UserAction
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'void OnUserEvent(UserAction action)
'{
'	switch (action)
'	{
'		case GeneratePdf pdf:
'			var renderer = New IronPdf.HtmlToPdf();
'			var document = renderer.RenderHtmlAsPdf(pdf.HtmlContent);
'			document.SaveAs(pdf.FileName);
'			break;
'		case ShowMessage msg:
'			MessageBox.Show(msg.Text);
'			break;
'		case ExitApplication:
'			Application.@Exit();
'			break;
'	}
'}
$vbLabelText   $csharpLabel

这让你能够用清晰的逻辑表示事件,并减少对公共对象类型或过于动态处理的依赖。

未来展望——C#是否会原生支持区分联合?

已经有提议在C#中添加区分联合的原生支持,特别是在对更富表现力的类型系统的需求不断增长的情况下。 尽管该语言尚未引入真正的union关键字,但C#正在持续发展——带来像记录、模式匹配和switch表达式等功能,逐步接近完整的区分联合功能。

.NET开发者若对现代、功能友好的语言结构感兴趣,将会想要密切关注这一领域。

最后的想法

在缺乏原生支持的情况下使用C#中的区分联合,仍然可以显著改善你在IronPDF应用程序中结构化和表示逻辑的方式。 通过利用记录、switch表达式和基类,你将使代码库更具可读性、可维护性,并且对错误更具抵御性——同时解锁更具声明性和表现力的方式来处理PDF相关任务。

如果你是一名构建现代、灵活的.NET应用程序的软件工程师,这种模式是你工具箱中的必备品。

立即免费试用IronPDF

准备好把你的C# PDF生成提升到一个新高度了吗? 下载IronPDF并开始免费试用。 无论你是从HTML生成文档、记录导出、还是使用区分联合自动化报告——IronPDF为你的应用提供了应有的强大和性能。

常见问题解答

如何在C#中实现判别联合?

在C#中,你可以通过定义一个基类和多个派生类来模拟判别联合,以代表每种可能情况。这种方法结合模式匹配,可以有效地管理多个相关的数据类型。

模式匹配在判别联合中的作用是什么?

在使用判别联合时,C#中的模式匹配至关重要,因为它可以让你以简明的方式处理联合的每个情况,从而提高代码可读性并减少多重条件语句的需求。

判别联合与C#中的枚举有何不同?

虽然判别联合和枚举都允许您定义一组固定的选项,但判别联合提供更大的灵活性,因为它们可以包含不同类型的数据,而枚举仅限于单一数据类型的命名常量。

我可以在使用判别联合时提高Iron Software的数据操作能力吗?

可以,Iron Software的产品,如IronPDF,可以通过提供高级数据处理能力来补充判别联合,简化在.NET应用程序中呈现和操作不同类型的数据。

在C#中使用判别联合的好处是什么?

判别联合通过允许您定义具有特定可能形式的类型,提供了增强的类型安全性、清晰度和代码维护性,方便进行强类型检查和减少错误。

使用判别联合如何影响代码的可读性?

通过允许开发人员清晰地定义并处理多个相关的数据类型,判别联合提高了代码的可读性。模式匹配更进一步简化了代码,减少了复杂的条件逻辑需求。

使用类来模拟C#中的判别联合的意义是什么?

在C#中使用类来模拟判别联合涉及创建一个基类和每种情况的派生类,提供了一种灵活且表达性强的方法来建模不同的相关类型,类似于函数式编程语言。

判别联合如何增强C#中的错误处理?

通过提供更精确的类型检查和启用模式匹配,判别联合可以提高错误处理能力,这有助于在编译时捕获潜在错误,从而增强应用程序的可靠性。

Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。