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

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

動的PDF生成を行う.NET開発者としてIronPDFを使用する際、特定の種類、例えばドキュメントデータ、ログメッセージ、ユーザーロール、エクスポートオプションを表現・管理する必要があります。 ここで、C#の区別された共用体の概念が登場します。

C#はF#やRustのようにネイティブで区別された共用体をサポートしていませんが、効果的にシミュレーションすることができます。 このブログ投稿では、C#で区別された共用体型を定義して使用する方法を掘り下げ、現実のPDF処理でIronPDFと組み合わせて適用する方法を示し、このパターンが提供する利点、特にパターンマッチングと組み合わせた際の利点を探ります。

C#の区別された共用体とは?

区別された共用体は、タグ付き共用体や共用体型とも呼ばれ、変数に限られた選択肢の中から1つの値を持たせることができ、各選択肢には一意のケース識別子が関連付けられています。

F#のような他の言語では、共用体キーワードを使用して定義することができます。 C#はこの機能をネイティブに提供していませんが、開発者はレコード、クラス、及びswitch式の巧みな組み合わせを利用してそれを模倣できます。

例えば:

public abstract record PdfAction;
public record GenerateReport(string ReportName) : PdfAction;
public record LogError(string Message) : PdfAction;
public record ExportToExcel(string FilePath) : PdfAction;
public abstract record PdfAction;
public record GenerateReport(string ReportName) : PdfAction;
public record LogError(string Message) : PdfAction;
public record ExportToExcel(string FilePath) : PdfAction;
Public MustOverride ReadOnly Property PdfAction() As record
public record GenerateReport(String ReportName) : PdfAction
public record LogError(String Message) : PdfAction
public record ExportToExcel(String FilePath) : PdfAction
$vbLabelText   $csharpLabel

上記の各レコードは、共用体の単一ケースを表します。 基本のPdfAction型が識別子の役割を果たします。

IronPDFのワークフローにおける区別された共用体の重要性

IronPDFを使用してPDFレポートジェネレーターを構築していて、ユーザーの入力に基づいて、PDFの生成やエラーログの記録、データのエクスポートなど、異なるアクションを実行する必要があるとします。

C#で区別された共用体を使用することで、これらのオプションタイプをクリーンに表現でき、コンパイル時の安全性、バグの削減、より明確なロジックが得られます。

IronPDFでの使用方法の一例を以下に示します。

void HandlePdfAction(PdfAction action)
{
    switch (action)
    {
        case GenerateReport r:
            var pdf = new IronPdf.HtmlToPdf().RenderHtmlAsPdf("<h1>" + r.ReportName + "</h1>");
            pdf.SaveAs(r.ReportName + ".pdf");
            break;
        case LogError e:
            Console.WriteLine("Logging Error: " + e.Message);
            break;
        case ExportToExcel x:
            Console.WriteLine("Exporting to Excel at " + x.FilePath);
            break;
        default:
            throw new NotSupportedException("Unknown action");
    }
}
void HandlePdfAction(PdfAction action)
{
    switch (action)
    {
        case GenerateReport r:
            var pdf = new IronPdf.HtmlToPdf().RenderHtmlAsPdf("<h1>" + r.ReportName + "</h1>");
            pdf.SaveAs(r.ReportName + ".pdf");
            break;
        case LogError e:
            Console.WriteLine("Logging Error: " + e.Message);
            break;
        case ExportToExcel x:
            Console.WriteLine("Exporting to Excel at " + x.FilePath);
            break;
        default:
            throw new NotSupportedException("Unknown action");
    }
}
Private Sub HandlePdfAction(ByVal action As PdfAction)
	Select Case action
'INSTANT VB TODO TASK: The following 'case' pattern variable is not converted by Instant VB:
'ORIGINAL LINE: case GenerateReport r:
		Case GenerateReport r
			Dim pdf = (New IronPdf.HtmlToPdf()).RenderHtmlAsPdf("<h1>" & r.ReportName & "</h1>")
			pdf.SaveAs(r.ReportName & ".pdf")
'INSTANT VB TODO TASK: The following 'case' pattern variable is not converted by Instant VB:
'ORIGINAL LINE: case LogError e:
		Case LogError e
			Console.WriteLine("Logging Error: " & e.Message)
'INSTANT VB TODO TASK: The following 'case' pattern variable is not converted by Instant VB:
'ORIGINAL LINE: case ExportToExcel x:
		Case ExportToExcel x
			Console.WriteLine("Exporting to Excel at " & x.FilePath)
		Case Else
			Throw New NotSupportedException("Unknown action")
	End Select
End Sub
$vbLabelText   $csharpLabel

このアプローチでは、コードを整理し、開発者がすべての可能なオプションを単一の場所で理解しやすくします。

C#での区別された共用体のシミュレート – 構造体 vs. レコード vs. クラス

C#は共用体キーワードを欠いていますが、区別された共用体をシミュレートする方法は次のとおりです。

  • レコード: 不変データに最適で、パターンマッチングをクリーンにサポートします。
  • クラス: 継承や参照セマンティクスに柔軟です。
  • 構造体: 値タイプには有用ですが、参照タイプや継承に関する柔軟性に欠けます。

C#区別された共用体(開発者向けに動作する方法):図1 - 構造体 vs. レコード vs. クラス

例:高スループットなPDFロギングなどで性能とメモリレイアウトが重要な場合、構造体区別された共用体の使用を検討する価値があります。

public interface IAction { }
public readonly struct SaveAction : IAction
{
    public string FileName { get; }
    public SaveAction(string fileName) => FileName = fileName;
}
public interface IAction { }
public readonly struct SaveAction : IAction
{
    public string FileName { get; }
    public SaveAction(string fileName) => FileName = fileName;
}
Public Interface IAction
End Interface
'INSTANT VB WARNING: VB has no equivalent to the C# readonly struct:
'ORIGINAL LINE: public readonly struct SaveAction : IAction
Public Structure SaveAction
	Implements IAction

	Public ReadOnly Property FileName() As String
	Public Sub New(ByVal fileName As String)
		Me.FileName = fileName
	End Sub
End Structure
$vbLabelText   $csharpLabel

注意:switch表現に依存する際に、特に構造体を使用するとパターンマッチングの利点が失われることがあります。

C#で区別された共用体を使用する利点

このソフトウェアエンジニアリングパターンを採用することには、いくつかの重要な利点があります。

  • コンパイル時の安全性: 実行時前にswitch表現の欠落したケースを見つけることができます。
  • より明確なロジック: 名前付きケースを使うことで、アクションを書く、コメントを付ける、推論するのが容易になります。
  • 関心の分離: 型階層ではなくデータに基づいて動作を分離します。
  • リファクタリングの容易さ: ケースの追加や削除がより簡単になります。

IronPDFと組み合わせることで、ユーザー入力の管理、レンダリングロジックの作成、異なる値パイプラインによる動的テンプレート作成がより簡単になります。

IronPDFと区別された共用体を使用するとき

このパターンが優れている実用的なシナリオをいくつか紹介します。

  • PDF生成ワークフロー: ドキュメントライフサイクル内の異なるステップ(生成、保存、メール)。
  • 許可モデル: 異なるユーザーアクセスレベルを表現します。
  • ロギングシステム: ログレベル(情報、エラー、デバッグ)に区別された共用体型を使用します。
  • ユニットテスト: テストアクションを共用体型として定義し、メンテナンスしやすいロジックツリーを作成します。
  • エクスポートオプション: 出力ターゲットをPDF、Excel、Wordとして共用体インスタンスとして表現します。

C#区別された共用体(開発者向けに動作する方法):図2 - .NETアプリでの共用体の一般的なシナリオ

例 – UIイベントからPDFアクションを処理する

UIイベントをキャプチャして、区別された共用体を使ってIronPDFタスクにルーティングする場合を考えてみましょう。

public abstract record UserAction;
public record GeneratePdf(string HtmlContent, string FileName) : UserAction;
public record ShowMessage(string Text) : UserAction;
public record ExitApplication() : UserAction;
void OnUserEvent(UserAction action)
{
    switch (action)
    {
        case GeneratePdf pdf:
            var renderer = new IronPdf.HtmlToPdf();
            var document = renderer.RenderHtmlAsPdf(pdf.HtmlContent);
            document.SaveAs(pdf.FileName);
            break;
        case ShowMessage msg:
            MessageBox.Show(msg.Text);
            break;
        case ExitApplication:
            Application.Exit();
            break;
    }
}
public abstract record UserAction;
public record GeneratePdf(string HtmlContent, string FileName) : UserAction;
public record ShowMessage(string Text) : UserAction;
public record ExitApplication() : UserAction;
void OnUserEvent(UserAction action)
{
    switch (action)
    {
        case GeneratePdf pdf:
            var renderer = new IronPdf.HtmlToPdf();
            var document = renderer.RenderHtmlAsPdf(pdf.HtmlContent);
            document.SaveAs(pdf.FileName);
            break;
        case ShowMessage msg:
            MessageBox.Show(msg.Text);
            break;
        case ExitApplication:
            Application.Exit();
            break;
    }
}
Public MustOverride ReadOnly Property UserAction() As record
public record GeneratePdf(String HtmlContent, String FileName) : UserAction
public record ShowMessage(String Text) : UserAction
public record ExitApplication() : UserAction
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'void OnUserEvent(UserAction action)
'{
'	switch (action)
'	{
'		case GeneratePdf pdf:
'			var renderer = New IronPdf.HtmlToPdf();
'			var document = renderer.RenderHtmlAsPdf(pdf.HtmlContent);
'			document.SaveAs(pdf.FileName);
'			break;
'		case ShowMessage msg:
'			MessageBox.Show(msg.Text);
'			break;
'		case ExitApplication:
'			Application.@Exit();
'			break;
'	}
'}
$vbLabelText   $csharpLabel

これにより、イベントを明確な論理で表現し、公開オブジェクトタイプや過度にダイナミックな処理への依存を減らすことができます。

将来の展望 – C#はネイティブで区別された共用体をサポートするのか?

より表現力豊かな型システムへの需要が高まる中、C#にネイティブサポートを追加する提案が既にされています。 言語はまだ本当の共用体キーワードを導入していませんが、C#は進化を続け、レコード、パターンマッチング、switch表現など、区別された共用体の機能に近づいています。

.NET開発者は、モダンで機能性に優れた言語構造に興味がある人は、この領域を注視すべきでしょう。

最終的な考え

ネイティブサポートがなくても、C#の区別された共用体の使用は、IronPDFアプリケーションでのロジックの構造と表現を大幅に改善します。 レコード、switch表現、および基底クラスを活用することで、コードベースをより読みやすく、保守しやすく、エラーへの耐性を高めるとともに、PDF関連タスクを扱うためのより宣言的で表現力豊かな方法を提供します。

モダンで柔軟な.NETアプリケーションを構築するソフトウェアエンジニアなら、このパターンをツールキットに加えるべきです。

今すぐIronPDFを無料で試しましょう

C#のPDF生成を次のレベルに引き上げる準備はできていますか? IronPDFをダウンロードして無料トライアルを始めましょう。 HTMLからドキュメントを生成するか、エクスポートをログするか、区別された共用体を使用してレポートを自動化するかにかかわらず、IronPDFはアプリが求めるパワーと性能を提供します。

よくある質問

C#で弁別共用体をどのように実装できますか?

C#では、ベースクラスと複数の派生クラスを定義して各可能なケースを表現することで弁別共用体をシミュレートできます。このアプローチは、パターンマッチングと組み合わせて、関連する複数のデータ型を効果的に管理することを可能にします。

弁別共用体におけるパターンマッチングの役割は何ですか?

C#でのパターンマッチングは、弁別共用体で作業する際に重要です。なぜなら、共用体の各ケースを簡潔に扱うことができ、コードの読みやすさを向上させ、複数の条件文を必要としなくなるからです。

弁別共用体はC#の列挙型とどのように比較されますか?

弁別共用体も列挙型も固定された選択肢のセットを定義することができますが、弁別共用体は異なる型のデータを保持できるため、より柔軟性があります。それに対して列挙型は単一のデータ型の名前付き定数に限定されます。

弁別共用体を使用しながらIron Softwareでデータ操作を強化できますか?

はい、IronPDFのようなIron Software製品は、弁別共用体と組み合わせて、高度なデータ処理能力を提供し、.NETアプリケーションで異なる種類のデータを操作して表示することを容易にします。

C#で弁別共用体を使用することの利点は何ですか?

弁別共用体は、特定の可能性のある形式で型を定義することで、C#コードの型安全性、明確性、およびメンテナンス性を向上させます。これにより、堅牢な型チェックが可能になり、エラーが減少します。

弁別共用体の使用はコードの可読性にどのように影響しますか?

開発者が関連する複数のデータ型を明確に定義して扱うことを可能にすることにより、弁別共用体はコードの可読性を向上させます。パターンマッチングは、複雑な条件ロジックを減らすことにより、さらにコードを簡素化します。

C#で弁別共用体をシミュレートするためにクラスを使用することの重要性は何ですか?

C#でクラスを使用して弁別共用体をシミュレートすることは、各ケースの派生クラスを持つベースクラスを作成することを含み、関数型プログラミング言語に似た関連する異なる型をモデル化するための柔軟で表現力豊かな方法を提供します。

C#でのエラー処理を弁別共用体でどのように強化できますか?

弁別共用体はより正確な型チェックを提供し、パターンマッチングを可能にすることでエラー処理を改善できます。これにより、潜在的なエラーがコンパイル時にキャッチされアプリケーションの信頼性が向上します。

Curtis Chau
テクニカルライター

Curtis Chauは、カールトン大学でコンピュータサイエンスの学士号を取得し、Node.js、TypeScript、JavaScript、およびReactに精通したフロントエンド開発を専門としています。直感的で美しいユーザーインターフェースを作成することに情熱を持ち、Curtisは現代のフレームワークを用いた開発や、構造の良い視覚的に魅力的なマニュアルの作成を楽しんでいます。

開発以外にも、CurtisはIoT(Internet of Things)への強い関心を持ち、ハードウェアとソフトウェアの統合方法を模索しています。余暇には、ゲームをしたりDiscordボットを作成したりして、技術に対する愛情と創造性を組み合わせています。