Pruebas en un entorno real
Pruebe en producción sin marcas de agua.
Funciona donde lo necesites.
Sindicatos discriminados, también conocidas como uniones etiquetadas o tipos suma, representan una potente herramienta para modelar datos que pueden adoptar diferentes formas, pero con casos posibles bien definidos y limitados. Aunque C# no tiene uniones nativas discriminadas como otros lenguajes(por ejemplo, F# o Rust), puede simular uniones discriminadas utilizando varias técnicas del lenguaje. En este tutorial, nos adentraremos en las uniones discriminadas, cómo implementarlas en C# y su caso de uso práctico con la aplicaciónBiblioteca IronPDF.
En términos sencillos, una unión discriminada es un tipo que puede contener una de varias formas o valores predefinidos. Proporciona una forma de crear una estructura a prueba de tipos que encapsula diferentes tipos o valores al tiempo que garantiza en tiempo de compilación que solo se tratan los casos válidos.
Imagínese una situación en la que desea representar el resultado de una operación. La operación puede tener éxito, devolviendo algunos datos, o fallar, devolviendo un mensaje de error. Una unión discriminada le permitiría representar estos dos posibles resultados en un solo tipo.
He aquí un ejemplo de cómo se puede simular una unión discriminada en C# utilizando una estructura de clases:
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);
}
Public MustInherit Class OperationResult(Of T)
Private Sub New()
End Sub
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
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
Public Shared Function CreateSuccess(ByVal value As T) As OperationResult(Of T)
Return New Success(value)
End Function
Public Shared Function CreateFailure(ByVal [error] As String) As OperationResult(Of T)
Return New Failure([error])
End Function
End Class
En este ejemplo, OperationResult
C# ofrece potentes funciones de concordancia de patrones que funcionan bien con uniones discriminadas. Ampliemos nuestra OperationResult
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")
};
'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")
' };
La expresión de conmutación aquí maneja tanto los casos de éxito como de fracaso de OperationResult
Puede ampliar la funcionalidad de las uniones discriminadas utilizando métodos de extensión. Por ejemplo, creemos un método de extensión para nuestro 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;
}
Public Module OperationResultExtensions
<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
Este método bool estático público comprueba si el resultado es una instancia del caso Éxito.
C# no tiene soporte nativo para uniones discriminadas como otros lenguajes, pero hay discusiones en curso en la comunidad sobre la adición de tal característica. Las uniones discriminadas nativas facilitarían la definición y el trabajo con tipos de unión sin necesidad de depender de jerarquías de clases.
Una de las principales ventajas de las uniones discriminadas es el tipo de seguridad que proporcionan. Dado que se conocen todos los casos posibles en tiempo de compilación, el compilador puede exigir que se traten todos los casos. De este modo se reducen los errores en tiempo de ejecución y el código es menos propenso a errores.
Por ejemplo, si se olvida de tratar un caso específico en una sentencia switch, el compilador producirá un error y le pedirá que trate el caso que falta. Esto es especialmente útil cuando se trata de estructuras de datos complejas con múltiples casos posibles.
IronPDF es una biblioteca PDF en C# que ayuda a los desarrolladores acrear archivos PDF a partir de HTML y les permite modificar archivos PDF sin complicaciones. Al trabajar con archivos PDF en C#, puede integrar IronPDF con uniones discriminadas para manejar diferentes escenarios al generar o procesar archivos PDF. Por ejemplo, puede haber un proceso que genere un PDF con éxito o que se encuentre con un error. Las uniones discriminadas permiten modelar este proceso con claridad. Creemos un ejemplo sencillo en el que generamos un PDF utilizando IronPDF y devolvemos el resultado como una unión discriminada.
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);
}
}
}
Imports IronPdf
Imports System
Public MustInherit Class PdfResult
Private Sub New()
End Sub
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
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
Public Shared Function CreateSuccess(ByVal pdf As PdfDocument) As PdfResult
Return New Success(pdf)
End Function
Public Shared Function CreateFailure(ByVal errorMessage As String) As PdfResult
Return New Failure(errorMessage)
End Function
End Class
Public Class PdfGenerator
Public Function GeneratePdf(ByVal htmlContent As String) As PdfResult
Try
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
Return PdfResult.CreateSuccess(pdf)
Catch ex As Exception
Return PdfResult.CreateFailure(ex.Message)
End Try
End Function
End Class
La clase PdfResult representa una unión discriminada con dos casos: Éxito y Fallo. El caso de Éxito contiene un PdfDocument, mientras que el caso de Fallo contiene un mensaje de error. El método GeneratePdf toma una cadena HTML, intenta generar un PDF utilizando IronPDF y devuelve el resultado como PdfResult. Si la generación del PDF tiene éxito, devuelve el caso Success con el PDF generado. Si se produce una excepción, devuelve el caso de fallo con el mensaje de error.
Las uniones discriminadas en C# proporcionan una forma potente y flexible de modelar datos con múltiples casos posibles. Aunque C# no admite uniones discriminadas, puede simularlas utilizando jerarquías de clases, concordancia de patrones y otras técnicas. El código resultante es más seguro, menos propenso a errores y más fácil de mantener.
IronPDF proporciona unprueba gratuita para ayudarle a hacerse una idea del software sin ningún coste inicial. Puedes explorar todas las características y ver cómo se alinean con tus necesidades. Después de su prueba, las licencias están disponibles desde $749.
9 productos API .NET para sus documentos de oficina