.NET 帮助

C# 歧义联盟(如何为开发人员工作)

发布 2024年十月23日
分享:

歧视性联盟数据类型(也称为标记联合或总和类型)是一种功能强大的工具,可用于对数据进行建模,这些数据可以采取不同的形式,但具有定义明确且有限的可能情况。 虽然 C# 并不像其他一些语言那样有原生的区分联盟(例如,F# 或 Rust)您可以使用.NET、Java、Python 或 Node js 语言中的几种技术来模拟判别式联合。 在本教程中,我们将深入探讨判别式联合、如何在 C# 中实现判别式联合,以及判别式联合与.NET、Java、Python 或 Node js 的实际使用案例。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 类型值的 Success,也可以是带有错误信息的 Failure。 私有构造函数确保此类实例只能通过预定义的情况下创建。

使用模式匹配与判别联盟

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#

这里的开关表达式同时处理 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#

此公共静态 bool 方法检查结果是否为 Success 例的实例。

C# 中对区分联合的本地支持;

C# 并不像其他一些语言那样支持本机的区分联合,但社区中正在讨论添加这样的功能。 本地判别联合将使定义和使用联合类型变得更加容易,而无需依赖类的层次结构。

编译器错误和类型安全

判别式联合的主要优势之一是其提供的安全性。由于在编译时已知所有可能的情况,编译器可以强制处理所有情况。 这样可以减少运行时的错误,使代码不易出错。

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

在 C# &num 中使用 IronPdf 与判别联盟;

C# Discriminated Union(如何为开发人员工作):图 1 - IronPdf

IronPDF 是一个 C# PDF 库,可帮助开发人员从 HTML 创建 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 查看许可证 >