跳至页脚内容
.NET 帮助

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

可辨识联合,也称为标记联合或和类型,是一种强大的工具,用于建模可以采取不同形式但具有明确且有限可能情况的数据。 虽然C#不像其他一些语言(例如F#或Rust)那样具有原生的可辨识联合,但您可以使用语言中的几种技术模拟可辨识联合。 在本教程中,我们将深入研究可辨识联合,如何在C#中实现它们,并通过IronPDF库探讨其实用用例。

什么是可辨识联合?

简而言之,可辨识联合是一种可以包含几种预定义形式或值的类型。 它提供了一种创建类型安全结构的方法,能够封装不同类型或值,同时在编译时确保只有有效的情况被处理。

想象一个您希望表示操作结果的场景。 操作可能成功,返回一些数据,或者失败,返回一条错误消息。 可辨识联合可以让您在单一类型中表示这两种可能的结果。

示例:在C#中模拟可辨识联合

以下是如何使用类结构在C#中模拟可辨识联合的示例:

// Define an abstract base class representing the operation result.
public abstract class OperationResult<T>
{
    // Private constructor to ensure the class cannot be instantiated directly.
    private OperationResult() { }

    // Nested class representing a successful operation result.
    public sealed class Success : OperationResult<T>
    {
        public T Value { get; }

        public Success(T value) => Value = value;

        public override string ToString() => $"Success: {Value}";
    }

    // Nested class representing a failed operation result.
    public sealed class Failure : OperationResult<T>
    {
        public string Error { get; }

        public Failure(string error) => Error = error;

        public override string ToString() => $"Failure: {Error}";
    }

    // Factory method to create a successful operation result.
    public static OperationResult<T> CreateSuccess(T value) => new Success(value);

    // Factory method to create a failed operation result.
    public static OperationResult<T> CreateFailure(string error) => new Failure(error);
}
// Define an abstract base class representing the operation result.
public abstract class OperationResult<T>
{
    // Private constructor to ensure the class cannot be instantiated directly.
    private OperationResult() { }

    // Nested class representing a successful operation result.
    public sealed class Success : OperationResult<T>
    {
        public T Value { get; }

        public Success(T value) => Value = value;

        public override string ToString() => $"Success: {Value}";
    }

    // Nested class representing a failed operation result.
    public sealed class Failure : OperationResult<T>
    {
        public string Error { get; }

        public Failure(string error) => Error = error;

        public override string ToString() => $"Failure: {Error}";
    }

    // Factory method to create a successful operation result.
    public static OperationResult<T> CreateSuccess(T value) => new Success(value);

    // Factory method to create a failed operation result.
    public static OperationResult<T> CreateFailure(string error) => new Failure(error);
}
' Define an abstract base class representing the operation result.
Public MustInherit Class OperationResult(Of T)
	' Private constructor to ensure the class cannot be instantiated directly.
	Private Sub New()
	End Sub

	' Nested class representing a successful operation result.
	Public NotInheritable Class Success
		Inherits OperationResult(Of T)

		Public ReadOnly Property Value() As T

		Public Sub New(ByVal value As T)
			Me.Value = value
		End Sub

		Public Overrides Function ToString() As String
			Return $"Success: {Value}"
		End Function
	End Class

	' Nested class representing a failed operation result.
	Public NotInheritable Class Failure
		Inherits OperationResult(Of T)

		Public ReadOnly Property [Error]() As String

		Public Sub New(ByVal [error] As String)
			Me.Error = [error]
		End Sub

		Public Overrides Function ToString() As String
			Return $"Failure: {[Error]}"
		End Function
	End Class

	' Factory method to create a successful operation result.
	Public Shared Function CreateSuccess(ByVal value As T) As OperationResult(Of T)
		Return New Success(value)
	End Function

	' Factory method to create a failed operation result.
	Public Shared Function CreateFailure(ByVal [error] As String) As OperationResult(Of T)
		Return New Failure([error])
	End Function
End Class
$vbLabelText   $csharpLabel

在此示例中,OperationResult<T>是一个抽象类,表示我们的可辨识联合类型。 它可以是一个带有类型T值的Success或带有错误消息的Failure。 私有构造函数确保这种类的实例只能通过预定义情况下创建。

使用模式匹配与可辨识联合

C#提供了强大的模式匹配功能,非常适合与可辨识联合一起使用。 让我们扩展我们的OperationResult<T>示例,通过一个方法使用switch表达式处理不同情况。

// Method to handle the result using pattern matching.
public string HandleResult(OperationResult<int> result) =>
    result switch
    {
        OperationResult<int>.Success success => $"Operation succeeded with value: {success.Value}",
        OperationResult<int>.Failure failure => $"Operation failed with error: {failure.Error}",
        _ => throw new InvalidOperationException("Unexpected result type")
    };
// Method to handle the result using pattern matching.
public string HandleResult(OperationResult<int> result) =>
    result switch
    {
        OperationResult<int>.Success success => $"Operation succeeded with value: {success.Value}",
        OperationResult<int>.Failure failure => $"Operation failed with error: {failure.Error}",
        _ => throw new InvalidOperationException("Unexpected result type")
    };
' Method to handle the result using pattern matching.
'INSTANT VB TODO TASK: The following 'switch expression' was not converted by Instant VB:
'public string HandleResult(OperationResult<int> result) => result switch
'	{
'		OperationResult<int>.Success success => $"Operation succeeded with value: {success.Value}",
'		OperationResult<int>.Failure failure => $"Operation failed with error: {failure.Error}",
'		_ => throw new InvalidOperationException("Unexpected result type")
'	};
$vbLabelText   $csharpLabel

这里的switch表达式处理OperationResult<int>SuccessFailure情况。 这确保在编译时覆盖所有可能情况,提供类型安全性并减少运行时错误的风险。

可辨识联合的扩展方法

您可以使用扩展方法扩展可辨识联合的功能。 例如,让我们为我们的OperationResult<T>创建一个扩展方法以确定结果是否成功:

// Static class to hold extension methods for OperationResult<T>.
public static class OperationResultExtensions
{
    // Extension method to check if the operation result indicates success. 
    public static bool IsSuccess<T>(this OperationResult<T> result) =>
        result is OperationResult<T>.Success;
}
// Static class to hold extension methods for OperationResult<T>.
public static class OperationResultExtensions
{
    // Extension method to check if the operation result indicates success. 
    public static bool IsSuccess<T>(this OperationResult<T> result) =>
        result is OperationResult<T>.Success;
}
' Static class to hold extension methods for OperationResult<T>.
Public Module OperationResultExtensions
	' Extension method to check if the operation result indicates success. 
	<System.Runtime.CompilerServices.Extension> _
	Public Function IsSuccess(Of T)(ByVal result As OperationResult(Of T)) As Boolean
		Return TypeOf result Is OperationResult(Of T).Success
	End Function
End Module
$vbLabelText   $csharpLabel

此静态方法检查结果是否是Success情况的实例。

C#中对可辨识联合的原生支持

C#不像其他一些语言那样对可辨识联合提供原生支持,但社区中正在进行关于添加该功能的讨论。 原生可辨识联合将更易于定义和使用联合类型,而无需依赖类层次结构。

编译器错误和类型安全

可辨识联合的一个主要优点是它们提供的类型安全性。由于所有可能的情况在编译时已知,编译器可以确保所有情况都得到处理。 这导致更少的运行时错误,使代码更不容易出错。

例如,如果您忘记在switch语句中处理某个特定情况,编译器会产生一个错误,提示您处理缺失的情况。 这在处理具有多种可能情况的复杂数据结构时尤其有用。

在C#中使用IronPDF与可辨识联合

C#可辨识联合(它如何为开发人员服务):图1 - IronPDF

IronPDF是一个C# PDF库,帮助开发人员从HTML创建PDF文件,并允许他们轻松修改PDF文件。 在C#中处理PDF时,您可以将IronPDF与可辨识联合结合使用,以处理在生成或处理PDF文件时的不同场景。 例如,您可能有一个成功生成PDF或遇到错误的过程。 可辨识联合允许您清晰地建模此过程。 让我们创建一个简单的示例,使用IronPDF生成PDF并将结果作为可辨识联合返回。

// Using directives for necessary namespaces.
using IronPdf;
using System;

// Define an abstract base class representing the PDF generation result.
public abstract class PdfResult
{
    // Private constructor to ensure the class cannot be instantiated directly.
    private PdfResult() { }

    // Nested class representing a successful PDF generation result.
    public sealed class Success : PdfResult
    {
        public PdfDocument Pdf { get; }

        public Success(PdfDocument pdf) => Pdf = pdf;

        public override string ToString() => "PDF generation succeeded";
    }

    // Nested class representing a failed PDF generation result.
    public sealed class Failure : PdfResult
    {
        public string ErrorMessage { get; }

        public Failure(string errorMessage) => ErrorMessage = errorMessage;

        public override string ToString() => $"PDF generation failed: {ErrorMessage}";
    }

    // Factory method to create a successful PDF result.
    public static PdfResult CreateSuccess(PdfDocument pdf) => new Success(pdf);

    // Factory method to create a failed PDF result.
    public static PdfResult CreateFailure(string errorMessage) => new Failure(errorMessage);
}

// Class to generate PDFs using IronPDF.
public class PdfGenerator
{
    // Method to generate a PDF from HTML content and return the result as a PdfResult.
    public PdfResult GeneratePdf(string htmlContent)
    {
        try
        {
            // Create a new ChromePdfRenderer instance.
            var renderer = new ChromePdfRenderer();

            // Attempt to render the HTML content as a PDF.
            var pdf = renderer.RenderHtmlAsPdf(htmlContent);

            // Return a success result with the generated PDF.
            return PdfResult.CreateSuccess(pdf);
        }
        catch (Exception ex)
        {
            // Return a failure result with the error message if an exception occurs.
            return PdfResult.CreateFailure(ex.Message);
        }
    }
}
// Using directives for necessary namespaces.
using IronPdf;
using System;

// Define an abstract base class representing the PDF generation result.
public abstract class PdfResult
{
    // Private constructor to ensure the class cannot be instantiated directly.
    private PdfResult() { }

    // Nested class representing a successful PDF generation result.
    public sealed class Success : PdfResult
    {
        public PdfDocument Pdf { get; }

        public Success(PdfDocument pdf) => Pdf = pdf;

        public override string ToString() => "PDF generation succeeded";
    }

    // Nested class representing a failed PDF generation result.
    public sealed class Failure : PdfResult
    {
        public string ErrorMessage { get; }

        public Failure(string errorMessage) => ErrorMessage = errorMessage;

        public override string ToString() => $"PDF generation failed: {ErrorMessage}";
    }

    // Factory method to create a successful PDF result.
    public static PdfResult CreateSuccess(PdfDocument pdf) => new Success(pdf);

    // Factory method to create a failed PDF result.
    public static PdfResult CreateFailure(string errorMessage) => new Failure(errorMessage);
}

// Class to generate PDFs using IronPDF.
public class PdfGenerator
{
    // Method to generate a PDF from HTML content and return the result as a PdfResult.
    public PdfResult GeneratePdf(string htmlContent)
    {
        try
        {
            // Create a new ChromePdfRenderer instance.
            var renderer = new ChromePdfRenderer();

            // Attempt to render the HTML content as a PDF.
            var pdf = renderer.RenderHtmlAsPdf(htmlContent);

            // Return a success result with the generated PDF.
            return PdfResult.CreateSuccess(pdf);
        }
        catch (Exception ex)
        {
            // Return a failure result with the error message if an exception occurs.
            return PdfResult.CreateFailure(ex.Message);
        }
    }
}
' Using directives for necessary namespaces.
Imports IronPdf
Imports System

' Define an abstract base class representing the PDF generation result.
Public MustInherit Class PdfResult
	' Private constructor to ensure the class cannot be instantiated directly.
	Private Sub New()
	End Sub

	' Nested class representing a successful PDF generation result.
	Public NotInheritable Class Success
		Inherits PdfResult

		Public ReadOnly Property Pdf() As PdfDocument

		Public Sub New(ByVal pdf As PdfDocument)
			Me.Pdf = pdf
		End Sub

		Public Overrides Function ToString() As String
			Return "PDF generation succeeded"
		End Function
	End Class

	' Nested class representing a failed PDF generation result.
	Public NotInheritable Class Failure
		Inherits PdfResult

		Public ReadOnly Property ErrorMessage() As String

		Public Sub New(ByVal errorMessage As String)
			Me.ErrorMessage = errorMessage
		End Sub

		Public Overrides Function ToString() As String
			Return $"PDF generation failed: {ErrorMessage}"
		End Function
	End Class

	' Factory method to create a successful PDF result.
	Public Shared Function CreateSuccess(ByVal pdf As PdfDocument) As PdfResult
		Return New Success(pdf)
	End Function

	' Factory method to create a failed PDF result.
	Public Shared Function CreateFailure(ByVal errorMessage As String) As PdfResult
		Return New Failure(errorMessage)
	End Function
End Class

' Class to generate PDFs using IronPDF.
Public Class PdfGenerator
	' Method to generate a PDF from HTML content and return the result as a PdfResult.
	Public Function GeneratePdf(ByVal htmlContent As String) As PdfResult
		Try
			' Create a new ChromePdfRenderer instance.
			Dim renderer = New ChromePdfRenderer()

			' Attempt to render the HTML content as a PDF.
			Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)

			' Return a success result with the generated PDF.
			Return PdfResult.CreateSuccess(pdf)
		Catch ex As Exception
			' Return a failure result with the error message if an exception occurs.
			Return PdfResult.CreateFailure(ex.Message)
		End Try
	End Function
End Class
$vbLabelText   $csharpLabel

PdfResult类表示具有两种情况的可辨识联合:SuccessFailureSuccess情况包含一个PdfDocument,而Failure情况包含一条错误消息。 GeneratePdf方法获取一个HTML字符串,尝试使用IronPDF生成PDF,并将结果作为PdfResult返回。 如果PDF生成成功,它会返回带有生成的PDF的Success情况。 如果发生异常,它会返回带有错误消息的Failure情况。

结论

C#可辨识联合(它如何为开发人员服务):图2 - 许可

C#中的可辨识联合提供了一种强大且灵活的方法来建模具有多种可能情况的数据。 虽然C#不支持可辨识联合,但您可以使用类层次结构、模式匹配和其他技术对其进行模拟。 生成的代码更加类型安全,更不容易出错,并且更易于维护。

IronPDF提供免费试用,帮助您免费体验软件。 您可以探索所有功能,并查看它们如何符合您的需求。 试用后,许可证从$799开始提供。

常见问题解答

如何在 C# 中创建判别联合?

您可以通过定义一个具有嵌套子类的抽象类在 C# 中创建判别联合。每个子类代表可能的情况,例如成功或错误状态,您可以使用模式匹配来处理这些情况。

IronPDF 库在处理判别联合中的作用是什么?

IronPDF 库可以与判别联合一起使用以管理 PDF 生成结果。通过将这些结果建模为判别联合,您可以确保类型安全,并处理成功的 PDF 创建及任何发生的错误。

模式匹配如何增强 C# 中的判别联合?

模式匹配通过允许开发人员优雅地处理每种可能的情况来增强 C# 中的判别联合。通过模式匹配,您可以安全地管理不同的结果,确保在编译时涵盖所有场景。

为什么判别联合对 C# 中的 PDF 生成有利?

判别联合对于 C# 中的 PDF 生成有益,因为它们提供了一种结构化的方法来处理成功和错误情况。此方法可确保在编译时解决潜在问题,减少 PDF 创建期间的运行时错误。

可以在 C# 中扩展判别联合以获得额外的功能吗?

是的,可以使用扩展方法扩展判别联合以获取其他功能。这允许您添加自定义行为,例如检查 PDF 生成的成功状态,而无需更改基础结构。

是否可以在没有本机支持的情况下在 C# 中模拟判别联合?

是的,尽管 C# 没有本机支持判别联合,但可以使用类层次结构来模拟它们。可以使用一个抽象的基类和嵌套类来表示不同的可能结果,例如成功或失败的情况。

C# 开发人员如何有效地处理 PDF 生成中的错误?

C# 开发人员可以通过使用判别联合来建模潜在结果来有效地处理 PDF 生成中的错误。此方法可确保在编译时解决错误,从而提高代码的可靠性和可维护性。

在 C# 项目中使用 IronPDF 与判别联合有何优势?

在 C# 项目中使用 IronPDF 与判别联合可以在 PDF 生成过程中提供强大的错误处理。这种组合可以清晰地区分成功的操作和错误,增强代码的安全性和可靠性。

判别联合如何促进 C# 中的类型安全?

判别联合通过确保在编译期间处理所有潜在情况来促进 C# 中的类型安全。这减少了运行时错误的可能性,使代码更具可预测性且更易于维护。

Curtis Chau
技术作家

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

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