Zum Fußzeileninhalt springen
.NET HILFE

C# Diskriminierte Union (Wie es für Entwickler funktioniert)

Diskriminierte Vereinigungen, auch bekannt als markierte Vereinigungen oder Summen-Typen, sind ein kraftvolles Werkzeug, um Daten zu modellieren, die unterschiedliche Formen annehmen können, aber mit gut definierten und begrenzten möglichen Fällen. Obwohl C# keine nativen diskriminierten Vereinigungen wie einige andere Sprachen (z.B. F# oder Rust) hat, können Sie diskriminierte Vereinigungen mit verschiedenen Techniken in der Sprache simulieren. In diesem Tutorial werden wir uns mit diskriminierten Vereinigungen befassen, wie man sie in C# implementiert und ihrem praktischen Anwendungsfall mit der IronPDF-Bibliothek.

Was ist eine Discriminated Union?

Einfach ausgedrückt ist eine diskriminierte Vereinigung ein Typ, der eine von mehreren vordefinierten Formen oder Werten annehmen kann. Sie bietet eine Möglichkeit, eine typsichere Struktur zu erstellen, die verschiedene Typen oder Werte kapselt und sicherstellt, dass zur Kompilierungszeit nur gültige Fälle behandelt werden.

Stellen Sie sich ein Szenario vor, in dem Sie das Ergebnis eines Vorgangs darstellen möchten. Der Vorgang kann entweder erfolgreich sein und einige Daten zurückgeben oder fehlschlagen und eine Fehlermeldung zurückgeben. Eine diskriminierte Vereinigung würde es Ihnen ermöglichen, diese beiden möglichen Ergebnisse in einem einzigen Typ darzustellen.

Beispiel: Simulierung der diskriminierten Vereinigung in C#;

Hier ist ein Beispiel, wie Sie eine diskriminierte Vereinigung in C# mit einer Klassenstruktur simulieren können:

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

In diesem Beispiel ist OperationResult eine abstrakte Klasse, die unseren Typ der diskriminierten Vereinigung darstellt. Es kann entweder ein Success mit einem Wert vom Typ T oder ein Failure mit einer Fehlermeldung sein. Der private Konstruktor stellt sicher, dass Instanzen einer solchen Klasse nur durch die vordefinierten Fälle erstellt werden können.

Verwendung von Pattern Matching mit diskriminierten Unions

C# bietet leistungsstarke Mustererkennungsfähigkeiten, die gut mit diskriminierten Vereinigungen funktionieren. Erweitern wir unser OperationResult-Beispiel mit einer Methode, die verschiedene Fälle mit einem Switch-Ausdruck behandelt.

// 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

Der Switch-Ausdruck hier behandelt sowohl die Success- als auch die Failure-Fälle des OperationResult<int>. Dies stellt sicher, dass alle möglichen Fälle zur Kompilierungszeit abgedeckt sind, bietet Typsicherheit und reduziert das Risiko von Laufzeitfehlern.

Erweiterungsmethoden für diskriminierte Unions

Sie können die Funktionalität von diskriminierten Vereinigungen mit Erweiterungsmethoden erweitern. Zum Beispiel erstellen wir eine Erweiterungsmethode für unser OperationResult, um festzustellen, ob das Ergebnis ein Erfolg ist:

// 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<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

Diese statische Methode überprüft, ob das Ergebnis eine Instanz des Success-Falles ist.

Native Unterstützung für diskriminierte Unions in C#

C# bietet keine native Unterstützung für diskriminierte Vereinigungen wie einige andere Sprachen, aber es gibt laufende Diskussionen in der Community über die Einführung einer solchen Funktion. Natürliche diskriminierte Vereinigungen würden es erleichtern, Vereinigungs-Typen zu definieren und mit ihnen zu arbeiten, ohne auf Klassenhierarchien angewiesen zu sein.

Compiler-Fehler und Typsicherheit

Einer der Hauptvorteile von diskriminierten Vereinigungen ist die von ihnen bereitgestellte Typsicherheit. Da alle möglichen Fälle zur Kompilierungszeit bekannt sind, kann der Compiler durchsetzen, dass alle Fälle behandelt werden. Dies führt zu weniger Laufzeitfehlern und macht den Code weniger fehleranfällig.

Wenn Sie beispielsweise vergessen, einen bestimmten Fall in einer Switch-Anweisung zu behandeln, erzeugt der Compiler einen Fehler und fordert Sie auf, den fehlenden Fall zu adressieren. Dies ist besonders nützlich, wenn man mit komplexen Datenstrukturen arbeitet, die mehrere mögliche Fälle haben.

Verwendung von IronPDF mit diskriminierten Unions in C#;

C# Diskriminierte Vereinigung (Wie es für Entwickler funktioniert): Abbildung 1 - IronPDF

IronPDF ist eine C# PDF-Bibliothek, die Entwicklern dabei hilft, PDF-Dateien aus HTML zu erstellen und es ihnen ermöglicht, PDF-Dateien ohne Probleme zu ändern. Wenn Sie mit PDFs in C# arbeiten, können Sie IronPDF mit diskriminierten Vereinigungen integrieren, um mit verschiedenen Szenarien bei der Erzeugung oder Verarbeitung von PDF-Dateien umzugehen. Zum Beispiel könnten Sie einen Prozess haben, der entweder erfolgreich ein PDF erstellt oder auf einen Fehler stößt. Diskriminierte Vereinigungen ermöglichen es Ihnen, diesen Prozess klar zu modellieren. Erstellen wir ein einfaches Beispiel, bei dem wir ein PDF mit IronPDF generieren und das Ergebnis als diskriminierte Vereinigung zurückgeben.

// 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

Die PdfResult-Klasse stellt eine diskriminierte Vereinigung mit zwei Fällen dar: Success und Failure. Der Success-Fall enthält ein PdfDocument, während der Failure-Fall eine Fehlermeldung enthält. Die GeneratePdf-Methode nimmt einen HTML-String, versucht, mit IronPDF ein PDF zu erzeugen, und gibt das Ergebnis als PdfResult zurück. Wenn die PDF-Erzeugung erfolgreich ist, gibt sie den Success-Fall mit dem erzeugten PDF zurück. Wenn eine Ausnahme auftritt, gibt sie den Failure-Fall mit der Fehlermeldung zurück.

Abschluss

C# Diskriminierte Vereinigung (Wie es für Entwickler funktioniert): Abbildung 2 - Lizenzierung

Diskriminierte Vereinigungen in C# bieten eine kraftvolle und flexible Möglichkeit, Daten mit mehreren möglichen Fällen zu modellieren. Obwohl C# keine Unterstützung für diskriminierte Vereinigungen bietet, können Sie sie mit Klassenhierarchien, Mustererkennung und anderen Techniken simulieren. Der resultierende Code ist typsicherer, weniger fehleranfällig und einfacher zu warten.

IronPDF bietet eine kostenlose Testversion, um Ihnen ein Gefühl für die Software zu geben, ohne dass Vorabkosten anfallen. Sie können alle Funktionen erkunden und sehen, wie sie mit Ihren Anforderungen übereinstimmen. Nach der Testversion sind Lizenzen ab $799 verfügbar.

Häufig gestellte Fragen

Wie kann ich eine diskriminierte Vereinigung in C# erstellen?

Sie können eine diskriminierte Vereinigung in C# erstellen, indem Sie eine abstrakte Klasse mit verschachtelten Unterklassen definieren. Jede Unterklasse repräsentiert einen möglichen Fall, wie einen Erfolgs- oder Fehlerzustand, und Sie können Musterabgleich verwenden, um diese Fälle zu behandeln.

Welche Rolle spielt die IronPDF-Bibliothek beim Umgang mit diskriminierten Vereinigungen?

Die IronPDF-Bibliothek kann zusammen mit diskriminierten Vereinigungen verwendet werden, um PDF-Generierungsergebnisse zu verwalten. Indem Sie diese Ergebnisse als diskriminierte Vereinigungen modellieren, können Sie Typsicherheit gewährleisten und sowohl erfolgreiche PDF-Erstellungen als auch auftretende Fehler behandeln.

Wie verbessert der Musterabgleich diskriminierte Vereinigungen in C#?

Der Musterabgleich verbessert diskriminierte Vereinigungen in C#, indem er Entwicklern ermöglicht, jeden möglichen Fall elegant zu behandeln. Mit Musterabgleich können Sie verschiedene Ergebnisse sicher verwalten und sicherstellen, dass alle Szenarien zur Kompilierungszeit abgedeckt sind.

Warum sind diskriminierte Vereinigungen vorteilhaft für die PDF-Erstellung in C#?

Diskriminierte Vereinigungen sind vorteilhaft für die PDF-Erstellung in C#, da sie eine strukturierte Möglichkeit bieten, Erfolgs- und Fehlerfälle zu behandeln. Diese Vorgehensweise stellt sicher, dass potenzielle Probleme zur Kompilierungszeit berücksichtigt werden, wodurch Laufzeitfehler während der PDF-Erstellung reduziert werden.

Können diskriminierte Vereinigungen in C# für zusätzliche Funktionalitäten erweitert werden?

Ja, diskriminierte Vereinigungen können mit zusätzlichen Funktionalitäten durch Erweiterungsmethoden erweitert werden. Dies ermöglicht es Ihnen, benutzerdefinierte Verhaltensweisen hinzuzufügen, wie beispielsweise das Überprüfen des Erfolgsstatus einer PDF-Generierung, ohne die Basisstruktur zu verändern.

Gibt es eine Möglichkeit, diskriminierte Vereinigungen in C# ohne native Unterstützung zu simulieren?

Ja, obwohl C# keine native Unterstützung für diskriminierte Vereinigungen hat, können sie durch Klassenhierarchien simuliert werden. Eine abstrakte Basisklasse kann mit verschachtelten Klassen verwendet werden, um verschiedene mögliche Ergebnisse, wie Erfolgs- oder Fehlerzustände, darzustellen.

Wie können C#-Entwickler Fehler bei der PDF-Erstellung effektiv handhaben?

C#-Entwickler können Fehler bei der PDF-Erstellung effektiv handhaben, indem sie diskriminierte Vereinigungen verwenden, um potenzielle Ergebnisse zu modellieren. Diese Vorgehensweise gewährleistet, dass Fehler zur Kompilierungszeit berücksichtigt werden, was die Zuverlässigkeit und Wartbarkeit des Codes verbessert.

Welche Vorteile bietet die Verwendung von IronPDF mit diskriminierten Vereinigungen für C#-Projekte?

Die Verwendung von IronPDF mit diskriminierten Vereinigungen in C#-Projekten bietet den Vorteil einer robusten Fehlerbehandlung während der PDF-Erstellung. Diese Kombination ermöglicht eine klare Unterscheidung zwischen erfolgreichen Operationen und Fehlern und verbessert die Codesicherheit und Zuverlässigkeit.

Wie tragen diskriminierte Vereinigungen zur Typsicherheit in C# bei?

Diskriminierte Vereinigungen tragen zur Typsicherheit in C# bei, indem sie sicherstellen, dass alle potenziellen Fälle während der Kompilierung behandelt werden. Dies reduziert die Wahrscheinlichkeit von Laufzeitfehlern und macht den Code vorhersehbarer und einfacher zu warten.

Jacob Mellor, Chief Technology Officer @ Team Iron
Chief Technology Officer

Jacob Mellor ist Chief Technology Officer bei Iron Software und ein visionärer Ingenieur, der führend in der C# PDF-Technologie ist. Als ursprünglicher Entwickler der Iron Software-Kerncodebasis hat er die Produktarchitektur des Unternehmens seit seiner Gründung gestaltet und zusammen mit CEO Cameron Rimington in ein Unternehmen ...

Weiterlesen