푸터 콘텐츠로 바로가기
.NET 도움말

C# Discriminated Union (개발자를 위한 작동 방식)

분류된 유니온은 태그가 있는 유니온 또는 합집합 유형으로도 알려져 있으며, 서로 다른 형태를 가질 수 있는 데이터를 모델링하는 강력한 도구를 나타냅니다. 하지만 가능한 경우는 잘 정의되어 있고 제한되어 있습니다. C#은 다른 언어들처럼 (예: F# 또는 Rust) 기본적으로 분류된 유니온을 지원하지 않지만, 언어 내의 여러 기술을 사용하여 분류된 유니온을 시뮬레이션할 수 있습니다. 이 튜토리얼에서는 분류된 유니온, C#에서 이를 구현하는 방법 및 IronPDF 라이브러리와의 실제 사용 사례를 다룰 것입니다.

분류된 유니온이란 무엇인가요?

간단히 말해, 분류된 유니온은 여러 사전 정의된 형태 또는 값을 가질 수 있는 유형입니다. 컴파일 타임에 유효한 경우만 처리된다는 것을 보장하면서 서로 다른 유형 또는 값을 캡슐화하는 타입 안전 구조를 만들 수 있는 방법을 제공합니다.

작업의 결과를 나타내려고 하는 시나리오를 상상해 보세요. 이 작업은 성공적으로 수행되어 일부 데이터를 반환하거나 실패하여 오류 메시지를 반환할 수 있습니다. 분류된 유니온은 이러한 두 가지 가능한 결과를 단일 유형으로 나타낼 수 있습니다.

예제: 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#은 분류된 유니온과 잘 작동하는 강력한 패턴 매칭 기능을 제공합니다. 스위치 표현식을 사용하여 다른 케이스를 처리하는 메서드로 우리의 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

여기 스위치 표현식은 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 케이스의 인스턴스인지 확인합니다.

C#에서 분류된 유니온의 기본 지원

C#은 다른 언어들처럼 기본적으로 분류된 유니온을 지원하지 않지만, 이러한 기능 추가에 대한 커뮤니티 내의 지속적인 논의가 있습니다. 기본적인 분류된 유니온은 클래스 계층구조에 의존하지 않고 유니온 유형을 정의하고 작업하는 것을 더 쉽게 만들 것입니다.

컴파일러 오류 및 타입 안전성

분류된 유니온의 주요 이점 중 하나는 제공되는 타입 안전성입니다. 모든 가능한 케이스를 컴파일 타임에 알고 있으므로, 컴파일러는 모든 경우가 처리되도록 강제할 수 있습니다. 이로 인해 런타임 오류가 줄어들고 코드가 오류에 덜 취약해집니다.

예를 들어, switch문의 특정 케이스를 처리하는 것을 잊으면, 컴파일러는 오류를 발생시켜 누락된 케이스를 처리하도록 유도합니다. 이는 여러 가지 가능한 케이스가 있는 복잡한 데이터 구조를 다룰 때 특히 유용합니다.

C#에서 분류된 유니온과 IronPDF 함께 사용하기

C# 차별화된 유니온 (개발자를 위한 작동 방식): 그림 1 - IronPDF

IronPDF는 개발자가 HTML에서 PDF 파일을 생성하고 아무런 문제 없이 PDF 파일을 수정할 수 있도록 도와주는 C# 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 클래스는 SuccessFailure 두 가지 케이스가 있는 차별화된 유니온을 나타냅니다. Success 케이스는 PdfDocument을 포함하고, Failure 케이스는 오류 메시지를 담고 있습니다. GeneratePdf 메서드는 HTML 문자열을 받아 IronPDF를 사용하여 PDF 생성을 시도하고, 결과를 PdfResult로 반환합니다. PDF 생성에 성공하면 생성된 PDF와 함께 Success 케이스를 반환합니다. 예외가 발생하면 오류 메시지를 담은 Failure 케이스를 반환합니다.

결론

C# 차별화된 유니온 (개발자를 위한 작동 방식): 그림 2 - 라이선싱

C#의 차별화된 합집합은 여러 가지 가능한 케이스의 데이터를 모델링하는 강력하고 유연한 방법을 제공합니다. C#은 차별화된 합집합을 지원하지 않지만, 클래스 계층, 패턴 매칭 및 기타 기술을 사용하여 이를 시뮬레이션할 수 있습니다. 결과적으로 코드가 타입 안전성이 높아지고 오류가 적어지며 유지 보수가 용이해집니다.

IronPDF는 사전 비용 없이 소프트웨어를 체험할 수 있는 무료 체험판을 제공합니다. 모든 기능을 탐험하고 자신의 요구와 어떻게 맞는지 확인할 수 있습니다. 체험판 후, 라이선스는 $799부터 시작하여 이용 가능합니다.

자주 묻는 질문

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#에서 타입 안전성에 기여합니다. 이는 실행 시간 오류의 가능성을 줄여주고, 코드를 더 예측 가능하고 쉽게 유지 관리할 수 있도록 합니다.

제이콥 멜러, 팀 아이언 최고기술책임자
최고기술책임자

제이콥 멜러는 Iron Software의 최고 기술 책임자(CTO)이자 C# PDF 기술을 개척한 선구적인 엔지니어입니다. Iron Software의 핵심 코드베이스를 최초로 개발한 그는 창립 초기부터 회사의 제품 아키텍처를 설계해 왔으며, CEO인 캐머런 리밍턴과 함께 회사를 NASA, 테슬라, 그리고 전 세계 정부 기관에 서비스를 제공하는 50명 이상의 직원을 보유한 기업으로 성장시켰습니다.

제이콥은 맨체스터 대학교에서 토목공학 학사 학위(BEng)를 최우등으로 취득했습니다(1998~2001). 1999년 런던에서 첫 소프트웨어 회사를 설립하고 2005년 첫 .NET 컴포넌트를 개발한 후, 마이크로소프트 생태계 전반에 걸쳐 복잡한 문제를 해결하는 데 전문성을 발휘해 왔습니다.

그의 대표 제품인 IronPDF 및 Iron Suite .NET 라이브러리는 전 세계적으로 3천만 건 이상의 NuGet 설치 수를 기록했으며, 그의 핵심 코드는 전 세계 개발자들이 사용하는 다양한 도구에 지속적으로 활용되고 있습니다. 25년의 실무 경험과 41년의 코딩 전문성을 바탕으로, 제이콥은 차세대 기술 리더들을 양성하는 동시에 기업 수준의 C#, Java, Python PDF 기술 혁신을 주도하는 데 주력하고 있습니다.

아이언 서포트 팀

저희는 주 5일, 24시간 온라인으로 운영합니다.
채팅
이메일
전화해