跳過到頁腳內容
.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 熱衷於創建直觀且美觀的用戶界面,喜歡使用現代框架並打造結構良好、視覺吸引人的手冊。

除了開發之外,Curtis 對物聯網 (IoT) 有著濃厚的興趣,探索將硬體和軟體結合的創新方式。在閒暇時間,他喜愛遊戲並構建 Discord 機器人,結合科技與創意的樂趣。