.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);
}

在本例中,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")
    };

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

此公共静态 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);
        }
    }
}

PdfResult 类表示有两种情况的判别联合:成功和失败。 成功案例包含一个 PdfDocument,而失败案例则包含一条错误信息。 GeneratePdf 方法接收 HTML 字符串,尝试使用 IronPDF 生成 PDF,并将结果作为 PdfResult 返回。 如果 PDF 生成成功,则返回成功案例和生成的 PDF。 如果出现异常,它将返回带有错误信息的失败案例。

结论

C# 识别联盟(如何为开发人员工作):图 2 - 许可

C# 中的判别联合提供了一种功能强大且灵活的方式,可对具有多种可能情况的数据进行建模。 虽然 C# 不支持判别联合,但您可以使用类层次结构、模式匹配和其他技术来模拟它们。 翻译后的代码类型更安全,错误更少,更易于维护。

IronPDF 提供了一个免费试用在不增加任何前期费用的情况下,帮助您了解软件。 您可以探索所有功能,看看它们如何满足您的需求。 在试用期结束后,许可证的价格起始于 $749。

乔尔迪·巴尔迪亚
乔尔迪·巴尔迪亚
软件工程师
Jordi 最擅长 Python、C# 和 C++,当他不在 Iron Software 运用技能时,他会进行游戏编程。作为产品测试、产品开发和研究的负责人之一,Jordi 为持续的产品改进增添了极大的价值。多样化的经验让他充满挑战和参与感,他说这是他在 Iron Software 工作中最喜欢的方面之一。Jordi 在佛罗里达州迈阿密长大,并在佛罗里达大学学习计算机科学和统计学。
< 前一页
C# HttpClient(面向开发人员的工作原理)
下一步 >
C# 新 GUID(如何为开发人员工作)