フッターコンテンツにスキップ
.NETヘルプ

C# Discriminated Union(開発者向けの仕組み)

判別共用体(タグ付き共用体または和型とも呼ばれます)は、異なる形を取る可能性があるデータをモデル化するための強力なツールです。明確に定義された限られたケースを持ちます。 C# は F# や Rust などの他の言語のようにネイティブな判別共用体をサポートしていませんが、いくつかの技術を使って言語内で判別共用体をシミュレートできます。 このチュートリアルでは、判別共用体について詳しく説明し、C# での実装方法と、IronPDF ライブラリを使った実用的な使用例を紹介します。

判別共用体とは?

簡単に言えば、判別共用体とは、いくつかの事前定義された形式または値を保持できるタイプです。 これは、異なるタイプまたは値をカプセル化し、コンパイル時に有効なケースのみが処理されることを確保した型安全な構造を作成する方法を提供します。

ある操作の結果を表現したいシナリオを想像してみてください。 操作は成功していくつかのデータを返すか、または失敗してエラーメッセージを返すことができます。 判別共用体は、これら2つの可能な結果を単一のタイプで表現することを可能にします。

Example: Simulating Discriminated Union in 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);
}
Imports System

' 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(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([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(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([error] As String) As OperationResult(Of T)
        Return New Failure([error])
    End Function
End Class
$vbLabelText   $csharpLabel

この例では、OperationResult<t> は判別共用体型を表す抽象クラスです。 これは、タイプ T の値を持つ Success か、エラー メッセージを持つ Failure のいずれかになります。 プライベートコンストラクタは、そのようなクラスのインスタンスが事前定義されたケースを通じてのみ作成されることを保証します。

パターンマッチングと判別共用体の使用

C# は判別共用体とうまく連携する強力なパターンマッチング機能を提供します。 switch 式を使用してさまざまなケースを処理するメソッドを追加して、OperationResult<t> の例を拡張してみましょう。

// 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(Of 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 ケースのインスタンスであるかどうかを確認します。

Native Support for Discriminated Unions in C

C#には、他のいくつかの言語のような判別共用体のネイティブサポートはありませんが、そのような機能を追加することについてコミュニティ内で継続的な議論があります。 ネイティブな判別共用体は、クラス階層に依存することなく、ユニオン型を定義し作業することを容易にします。

コンパイラエラーと型の安全性

判別共用体の主要な利点の一つは、それらが提供する型の安全性です。すべての可能なケースがコンパイル時に知られているため、コンパイラはすべてのケースが処理されることを強制できます。 これにより、実行時エラーが減少し、コードがエラーに対してより頑健になります。

たとえば、switch 文で特定のケースを処理するのを忘れると、コンパイラはエラーを生成し、欠落したケースを処理するよう促します。 これは、複数の可能なケースを持つ複雑なデータ構造を扱う際に特に有用です。

Using IronPDF with Discriminated Unions in C

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 クラスは、2 つのケース、SuccessFailure を持つ判別ユニオンを表します。 Success の場合、PdfDocument が含まれ、Failure の場合、エラー メッセージが保持されます。 GeneratePdf メソッドは HTML 文字列を受け取り、 IronPDFを使用して PDF の生成を試み、結果を PdfResult として返します。 PDF 生成が成功した場合、生成された PDF とともに Success ケースが返されます。 例外が発生した場合は、エラー メッセージとともに Failure ケースを返します。

結論

C# 判別ユニオン (開発者にとっての仕組み): 図 2 - ライセンス

C# の判別共用体は、複数の可能なケースを持つデータをモデル化する強力で柔軟な方法を提供します。 C# は判別共用体をサポートしていませんが、クラスの階層、パターンマッチング、その他の技術を使ってそれらをシミュレートできます。 結果として得られるコードは、型安全で、エラーが発生しにくく、メンテナンスが容易です。

IronPDF は、前払い費用なしでソフトウェアを体験するのに役立つ無料トライアルを提供します。 すべての機能を探索して、プロジェクトのニーズにどのように応えるかを確認できます。 試用期間終了後は、ライセンスは $999 からご利用いただけます。

よくある質問

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# の型安全性に貢献します。これにより、ランタイムエラーの可能性が減少し、コードがより予測可能で保守しやすくなります。

Jacob Mellor、Ironチームの最高技術責任者(CTO)
最高技術責任者(CTO)

ジェイコブ・メラーはIron Softwareの最高技術責任者(CTO)であり、C# PDFテクノロジーを開拓する先見的なエンジニアです。Iron Softwareのコアコードベースを支えるオリジナル開発者として、彼は創業以来、会社の製品アーキテクチャを形成し、CEOのCameron Rimingtonとともに、会社をNASA、Tesla、および世界的な政府機関にサービスを提供する50人以上の会社に変えました。1999年にロンドンで最初のソフトウェアビジネスを開業し、2005年に最初 for .NETコンポーネントを作成した後、Microsoftのエコシステム全体で複雑な問題を解決することを専門としました。

彼の主要なIronPDFとIron Suite .NETライブラリは、世界中で3000万以上のNuGetインストールを達成し、彼の基礎となるコードは世界中で使用されている開発者ツールに力を与え続けています。25年の商業経験と41年のコーディングの専門知識を持つJacobは、次世代の技術リーダーを指導しながら、エンタープライズグレードのC#、Java、Python PDFテクノロジーにおけるイノベーションの推進に注力しています。

アイアンサポートチーム

私たちは週5日、24時間オンラインで対応しています。
チャット
メール
電話してね