.NET 幫助

C# 判別聯合(它如何為開發者工作)

發佈 2024年10月23日
分享:

區別聯合,也稱為標記聯合或和類型,是一種強大的工具,用於建模可以採取不同形式的數據,但這些形式具有明確且有限的可能情況。 雖然 C# 沒有像一些其他語言那樣的原生判別聯合類型(例如 F# 或 Rust),您可以使用多種技術來模擬區分聯合。 在本教程中,我們將深入探討區分聯合,如何在 C# 中實現它們,以及它們的實際使用案例。IronPDF 庫.

什麼是區分聯合?

簡單來說,判別聯合是一種可以持有多個預定義的形式或值中的一種類型。 它提供了一種建立類型安全結構的方法,封裝不同的類型或值,同時在編譯時確保只處理有效的情況。

想像一個情境,你想表達一個操作的結果。 該操作可能成功,返回一些數據,或失敗,返回錯誤訊息。 判別聯合將允許您在單一類型中表示這兩種可能的結果。

範例:在C#中模擬區分聯合

下面是一個如何在 C# 中使用類結構模擬區分聯合的例子:

public abstract class OperationResult<T>
{
    private OperationResult() { }
    public sealed class Success : OperationResult<T>
    {
        public T Value { get; }
        public Success(T value) => Value = value;
        public override string ToString() => $"Success: {Value}";
    }
    public sealed class Failure : OperationResult<T>
    {
        public string Error { get; }
        public Failure(string error) => Error = error;
        public override string ToString() => $"Failure: {Error}";
    }
    public static OperationResult<T> CreateSuccess(T value) => new Success(value);
    public static OperationResult<T> CreateFailure(string error) => new Failure(error);
}
public abstract class OperationResult<T>
{
    private OperationResult() { }
    public sealed class Success : OperationResult<T>
    {
        public T Value { get; }
        public Success(T value) => Value = value;
        public override string ToString() => $"Success: {Value}";
    }
    public sealed class Failure : OperationResult<T>
    {
        public string Error { get; }
        public Failure(string error) => Error = error;
        public override string ToString() => $"Failure: {Error}";
    }
    public static OperationResult<T> CreateSuccess(T value) => new Success(value);
    public static OperationResult<T> CreateFailure(string error) => new Failure(error);
}
Public MustInherit Class OperationResult(Of T)
	Private Sub New()
	End Sub
	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
	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
	Public Shared Function CreateSuccess(ByVal value As T) As OperationResult(Of T)
		Return New Success(value)
	End Function
	Public Shared Function CreateFailure(ByVal [error] As String) As OperationResult(Of T)
		Return New Failure([error])
	End Function
End Class
VB   C#

在此範例中,OperationResult是一個抽象類,代表我們的判別聯合類型。 它可以是類型為 T 的成功,或是帶有錯誤信息的失敗。 私有的構造函數確保這類類別的實例只能通過預定義的案例來創建。

使用模式匹配與辨別聯合體

C# 提供強大的模式匹配功能,非常適合與區分聯合一起使用。 讓我們擴展我們的 OperationResult使用 switch 表達式處理不同案例的方法範例。

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")
    };
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")
    };
'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")
'	};
VB   C#

此處的 switch 表達式處理 OperationResult 的成功和失敗情況。. 這確保了在編譯時涵蓋所有可能的情況,提供類型安全並降低運行時錯誤的風險。

區分聯合的擴展方法

您可以使用擴展方法來擴展區分聯合的功能。 例如,讓我們為我們的 OperationResult 創建一個擴展方法。以判斷結果是否成功:

public static class OperationResultExtensions
{
    public static bool IsSuccess<T>(this OperationResult<T> result) =>
        result is OperationResult<T>.Success;
}
public static class OperationResultExtensions
{
    public static bool IsSuccess<T>(this OperationResult<T> result) =>
        result is OperationResult<T>.Success;
}
Public Module OperationResultExtensions
	<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
VB   C#

此公有靜態布林方法檢查結果是否為 Success 情況的實例。

在 C# 中對區分聯合的原生支持

C#不像某些其他語言那樣對判別聯合有原生的支持,但社群中正在進行關於添加此功能的討論。 原生辨別聯合將使定義和使用聯合類型變得更容易,無需依賴於類別層次結構。

編譯器錯誤和類型安全性

區分聯合的其中一個主要優勢是它們提供的類型安全性。由於所有可能的情況在編譯時就已知,編譯器可以確保所有情況都得到處理。 這樣可以減少運行時錯誤,使程式碼不易出錯。

例如,如果您忘記在 switch 語句中處理特定情況,編譯器將產生錯誤,提醒您解決缺少的情況。 這在處理具有多種可能情況的複雜數據結構時尤其有用。

在 C# 中使用 IronPDF 和辨别联合

C# 差異聯合(對開發者的工作機制):圖 1 - IronPDF

IronPDF 是一個 C# PDF 程式庫,幫助開發人員從 HTML 創建 PDF 文件並允許他們輕鬆修改PDF文件。 在使用 C# 處理 PDF 時,您可以將 IronPDF 與判別聯合結合,來處理不同的情境以生成或處理 PDF 文件。 例如,您可能有一個流程,可以成功生成 PDF,或遇到錯誤。 判別聯合體允許您清楚地建模此過程。 讓我們創建一個簡單的例子,使用IronPDF生成PDF,並將結果作為一個區別聯合返回。

using IronPdf;
using System;
public abstract class PdfResult
{
    private PdfResult() { }
    public sealed class Success : PdfResult
    {
        public PdfDocument Pdf { get; }
        public Success(PdfDocument pdf) => Pdf = pdf;
        public override string ToString() => "PDF generation succeeded";
    }
    public sealed class Failure : PdfResult
    {
        public string ErrorMessage { get; }
        public Failure(string errorMessage) => ErrorMessage = errorMessage;
        public override string ToString() => $"PDF generation failed: {ErrorMessage}";
    }
    public static PdfResult CreateSuccess(PdfDocument pdf) => new Success(pdf);
    public static PdfResult CreateFailure(string errorMessage) => new Failure(errorMessage);
}
public class PdfGenerator
{
    public PdfResult GeneratePdf(string htmlContent)
    {
        try
        {
            var renderer = new ChromePdfRenderer();
            var pdf = renderer.RenderHtmlAsPdf(htmlContent);
            return PdfResult.CreateSuccess(pdf);
        }
        catch (Exception ex)
        {
            return PdfResult.CreateFailure(ex.Message);
        }
    }
}
using IronPdf;
using System;
public abstract class PdfResult
{
    private PdfResult() { }
    public sealed class Success : PdfResult
    {
        public PdfDocument Pdf { get; }
        public Success(PdfDocument pdf) => Pdf = pdf;
        public override string ToString() => "PDF generation succeeded";
    }
    public sealed class Failure : PdfResult
    {
        public string ErrorMessage { get; }
        public Failure(string errorMessage) => ErrorMessage = errorMessage;
        public override string ToString() => $"PDF generation failed: {ErrorMessage}";
    }
    public static PdfResult CreateSuccess(PdfDocument pdf) => new Success(pdf);
    public static PdfResult CreateFailure(string errorMessage) => new Failure(errorMessage);
}
public class PdfGenerator
{
    public PdfResult GeneratePdf(string htmlContent)
    {
        try
        {
            var renderer = new ChromePdfRenderer();
            var pdf = renderer.RenderHtmlAsPdf(htmlContent);
            return PdfResult.CreateSuccess(pdf);
        }
        catch (Exception ex)
        {
            return PdfResult.CreateFailure(ex.Message);
        }
    }
}
Imports IronPdf
Imports System
Public MustInherit Class PdfResult
	Private Sub New()
	End Sub
	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
	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
	Public Shared Function CreateSuccess(ByVal pdf As PdfDocument) As PdfResult
		Return New Success(pdf)
	End Function
	Public Shared Function CreateFailure(ByVal errorMessage As String) As PdfResult
		Return New Failure(errorMessage)
	End Function
End Class
Public Class PdfGenerator
	Public Function GeneratePdf(ByVal htmlContent As String) As PdfResult
		Try
			Dim renderer = New ChromePdfRenderer()
			Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
			Return PdfResult.CreateSuccess(pdf)
		Catch ex As Exception
			Return PdfResult.CreateFailure(ex.Message)
		End Try
	End Function
End Class
VB   C#

PdfResult 類別表示具有兩種情況的區分聯合:成功和失敗。 成功的情況包含一個 PdfDocument,而失敗的情況則存有一個錯誤信息。 GeneratePdf 方法接受一個 HTML 字串,嘗試使用 IronPDF 生成 PDF,並將結果作為 PdfResult 返回。 如果 PDF 生成成功,將返回包含生成的 PDF 的成功案例。 如果發生異常,它將回傳失敗案例和錯誤訊息。

結論

C# 列舉聯合(對開發人員的運作方式):圖 2 - 授權

C# 中的歧視性聯合提供了一種強大且靈活的方式來建模具有多種可能情況的數據。 雖然 C# 不支援辨別聯合,但您可以使用類別繼承、模式匹配和其他技術來模擬它們。 生成的代碼更具有類型安全性,減少錯誤,且更易於維護。

IronPDF 提供一個免費試用以便在不需預付任何成本的情況下,幫助您了解軟體的使用感受。 您可以探索所有功能,看看它們如何符合您的需求。 試用期結束後,授權起價為 $749。

< 上一頁
C# HttpClient(開發人員如何使用)
下一個 >
C# 新的 GUID(如何為開發者運作)

準備開始了嗎? 版本: 2024.12 剛剛發布

免費 NuGet 下載 總下載次數: 11,622,374 查看許可證 >