AYUDA .NET

C# Generics (Cómo funciona para los desarrolladores)

Actualizado 3 de abril, 2024
Compartir:

Los genéricos de C# introducen una forma de diseñar clases, métodos, interfaces y delegados en los que el tipo de datos que gestionan puede especificarse como parámetro. Este concepto, conocido como parámetro de tipo genérico, permite crear componentes de código flexibles y reutilizables. Utilizando genéricos puede maximizar la reutilización del código, la seguridad de tipos y el rendimiento. Por ejemplo, una clase genérica puede definirse una vez pero instanciarse con varios tipos de datos, lo que ofrece versatilidad e integridad de tipos. En este artículo, aprenderemos los conceptos básicos de C# Generics y Biblioteca IronPDF.

Conceptos básicos de las clases genéricas

Una clase genérica en C# es un plano para crear una clase con un marcador de posición para el tipo que contiene o sobre el que opera. Este marcador de posición, a menudo denotado por T, representa un parámetro de tipo que se especifica cuando se instancia la clase. Podemos crear clases genéricas con el parámetro de tipo T para manejar varios tipos de datos. Las clases genéricas son particularmente útiles para las clases de colección, como listas, colas y tablas hash, ya que pueden contener cualquier tipo de datos al tiempo que garantizan la seguridad de tipo y reducen la necesidad de casting.

Ejemplo sencillo de clase genérica

Considere una clase genérica llamada Caja que está diseñada para almacenar un valor de cualquier tipo:

public class Box<T>
{
    private T data;
    public Box(T data) { this.data = data; }
    public T Data { get { return data; } }
}
public class Box<T>
{
    private T data;
    public Box(T data) { this.data = data; }
    public T Data { get { return data; } }
}
Public Class Box(Of T)
'INSTANT VB NOTE: The field data was renamed since Visual Basic does not allow fields to have the same name as other class members:
	Private data_Conflict As T
	Public Sub New(ByVal data As T)
		Me.data_Conflict = data
	End Sub
	Public ReadOnly Property Data() As T
		Get
			Return data_Conflict
		End Get
	End Property
End Class
VB   C#

Para utilizar esta clase, se crea una instancia especificando el tipo real para T:

Box<int> integerBox = new Box<int>(123);
Box<string> stringBox = new Box<string>("Hello");
Box<int> integerBox = new Box<int>(123);
Box<string> stringBox = new Box<string>("Hello");
Dim integerBox As New Box(Of Integer)(123)
Dim stringBox As New Box(Of String)("Hello")
VB   C#

Este código ilustra cómo una sola clase (Caja) puede adaptarse para almacenar distintos tipos de datos (int, string)mostrando el poder de los genéricos para la reutilización de código y la seguridad de tipos.

Implementación de métodos genéricos

Los métodos genéricos son similares a las clases genéricas, pero se definen con parámetros de tipo a nivel de método. Esto permite crear métodos que pueden operar sobre diferentes tipos estando definidos en una clase no genérica o en una genérica.

Ejemplo de método genérico

He aquí un método que intercambia dos elementos en un array de cualquier tipo:

public class Utility
{
    public static void Swap<T>(ref T lhs, ref T rhs)
    {
        T temp = lhs;
        lhs = rhs;
        rhs = temp;
    }
}
public class Utility
{
    public static void Swap<T>(ref T lhs, ref T rhs)
    {
        T temp = lhs;
        lhs = rhs;
        rhs = temp;
    }
}
Public Class Utility
	Public Shared Sub Swap(Of T)(ByRef lhs As T, ByRef rhs As T)
		Dim temp As T = lhs
		lhs = rhs
		rhs = temp
	End Sub
End Class
VB   C#

El uso del método anterior puede ser el siguiente:

int a = 1, b = 2;
Utility.Swap<int>(ref a, ref b);
string first = "world", second = "hello";
Utility.Swap(ref first, ref second);
int a = 1, b = 2;
Utility.Swap<int>(ref a, ref b);
string first = "world", second = "hello";
Utility.Swap(ref first, ref second);
Dim a As Integer = 1, b As Integer = 2
Utility.Swap(Of Integer)(a, b)
Dim first As String = "world", second As String = "hello"
Utility.Swap(first, second)
VB   C#

Exploración de interfaces genéricas y delegados

Las interfaces genéricas y los delegados permiten definir contratos y métodos de devolución de llamada que pueden operar con cualquier tipo. Implementar una interfaz genérica o utilizar un delegado genérico en su clase o método mejora la flexibilidad y la reutilización del código.

Ejemplo de interfaz genérica

Una interfaz genérica de repositorio para operaciones de acceso a datos podría tener este aspecto:

public interface IRepository<T>
{
    void Add(T item);
    T GetById(int id);
    IEnumerable<T> GetAll();
}
public interface IRepository<T>
{
    void Add(T item);
    T GetById(int id);
    IEnumerable<T> GetAll();
}
Public Interface IRepository(Of T)
	Sub Add(ByVal item As T)
	Function GetById(ByVal id As Integer) As T
	Function GetAll() As IEnumerable(Of T)
End Interface
VB   C#

Esta interfaz puede ser implementada por cualquier clase para manejar tipos de datos específicos, permitiendo patrones de acceso a datos consistentes a través de diferentes tipos.

Ejemplo de delegado genérico

Se puede utilizar un delegado genérico para definir una llamada de retorno segura:

public delegate void Action<T>(T item);
public delegate void Action<T>(T item);
Public Delegate Sub Action(Of T)(ByVal item As T)
VB   C#

Utilización de colecciones genéricas

Clases genéricas de colección, como List, Diccionario<TKey, TValue>, y otros del espacio de nombres System.Collections.Generic, ofrecen colecciones eficientes y seguras para almacenar y manipular datos de cualquier tipo específico. Estas colecciones son superiores a sus homólogas no genéricas porque eliminan la necesidad de hacer castings y reducen los errores en tiempo de ejecución.

List<string> names = new List<string>();
names.Add("Alice");
names.Add("Bob");
Dictionary<int, string> keyValuePairs = new Dictionary<int, string>();
keyValuePairs.Add(1, "One");
keyValuePairs.Add(2, "Two");
List<string> names = new List<string>();
names.Add("Alice");
names.Add("Bob");
Dictionary<int, string> keyValuePairs = new Dictionary<int, string>();
keyValuePairs.Add(1, "One");
keyValuePairs.Add(2, "Two");
Dim names As New List(Of String)()
names.Add("Alice")
names.Add("Bob")
Dim keyValuePairs As New Dictionary(Of Integer, String)()
keyValuePairs.Add(1, "One")
keyValuePairs.Add(2, "Two")
VB   C#

Creación de tipos genéricos personalizados

Además de utilizar los tipos genéricos incorporados, puede crear los suyos propios para encapsular operaciones comunes a distintos tipos de datos, pero que deben gestionarse de forma específica para cada tipo. Este enfoque es especialmente útil para crear bibliotecas, marcos de trabajo o utilidades que vayan a utilizarse con distintos tipos de datos.

Ejemplo de tipo genérico personalizado

Considere una clase genérica Resultado que encapsula los resultados de la operación junto con una bandera de éxito y un mensaje opcional:

public class Result<T>
{
    public bool Success { get; private set; }
    public T Data { get; private set; }
    public string Message { get; private set; }
    public Result(bool success, T data, string message = "")
    {
        Success = success;
        Data = data;
        Message = message;
    }
}
public class Result<T>
{
    public bool Success { get; private set; }
    public T Data { get; private set; }
    public string Message { get; private set; }
    public Result(bool success, T data, string message = "")
    {
        Success = success;
        Data = data;
        Message = message;
    }
}
Public Class Result(Of T)
	Private privateSuccess As Boolean
	Public Property Success() As Boolean
		Get
			Return privateSuccess
		End Get
		Private Set(ByVal value As Boolean)
			privateSuccess = value
		End Set
	End Property
	Private privateData As T
	Public Property Data() As T
		Get
			Return privateData
		End Get
		Private Set(ByVal value As T)
			privateData = value
		End Set
	End Property
	Private privateMessage As String
	Public Property Message() As String
		Get
			Return privateMessage
		End Get
		Private Set(ByVal value As String)
			privateMessage = value
		End Set
	End Property
	Public Sub New(ByVal success As Boolean, ByVal data As T, Optional ByVal message As String = "")
		Me.Success = success
		Me.Data = data
		Me.Message = message
	End Sub
End Class
VB   C#

IronPDF: C# Biblioteca PDF

IronPDF es una completa biblioteca diseñada para que los desarrolladores .NET puedan crear, editar y extraer documentos PDF dentro de sus aplicaciones. IronPDF ayuda en generar PDF a partir de HTML edición de PDF existentes, conversión de PDF a imágenes y mucho más. Aunque IronPDF en sí no se basa en genéricos, entender cómo interactuar con esta biblioteca en un entorno C# puede mejorar enormemente las capacidades de gestión de documentos de su aplicación.

Ejemplo de código: Uso de la palabra clave virtual con IronPDF

La idea de utilizar genéricos aquí es crear un método reutilizable que pueda generar un PDF a partir de cualquier cadena HTML dada. Este método será genérico, permitiéndonos especificar diferentes tipos de metadatos o configuraciones según sea necesario.

En primer lugar, vamos a definir una clase genérica simple que contendrá nuestras opciones de generación de PDF. A efectos de demostración, esta clase será básica, pero puede ampliarla con más propiedades para adaptarla a sus necesidades.

public class PdfOptions<T>
{
    public T Metadata { get; set; }
    public string HtmlContent { get; set; }
}
public class PdfOptions<T>
{
    public T Metadata { get; set; }
    public string HtmlContent { get; set; }
}
Public Class PdfOptions(Of T)
	Public Property Metadata() As T
	Public Property HtmlContent() As String
End Class
VB   C#

Ahora, vamos a crear un método estático que genere un PDF utilizando IronPDF, aprovechando nuestro PdfOptionsclase. Este método tomará una instancia de PdfOptionscomo parámetro, mostrando el uso de genéricos en acción.

public static class PdfGenerator
{
    public static void GeneratePdf<T>(PdfOptions<T> options)
    {
        //  Inicializar el renderizador IronPDF HtmlToPdf
        var renderer = new ChromePdfRenderer();
        //  Opcional: Aplique aquí cualquier opción del renderizador. Por ejemplo, establecer el tamaño del papel.
        renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
        //  Generar el PDF a partir del contenido HTML
        var pdfDocument = renderer.RenderHtmlAsPdf(options.HtmlContent);
        //  Opcional: Aquí, puede utilizar options.Metadata de alguna manera, dependiendo de su tipo genérico T.
        //  Para simplificar, sólo imprimiremos los metadatos en la consola si son de tipo cadena.
        if (options.Metadata is string metadataString)
        {
            Console.WriteLine($"Metadata: {metadataString}");
        }
        //  Guardar el PDF en un archivo
        var fileName = $"GeneratedPdf_{DateTime.Now.Ticks}.pdf";
        pdfDocument.SaveAs(fileName);
        Console.WriteLine($"PDF generated and saved as {fileName}");
    }
}
public static class PdfGenerator
{
    public static void GeneratePdf<T>(PdfOptions<T> options)
    {
        //  Inicializar el renderizador IronPDF HtmlToPdf
        var renderer = new ChromePdfRenderer();
        //  Opcional: Aplique aquí cualquier opción del renderizador. Por ejemplo, establecer el tamaño del papel.
        renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
        //  Generar el PDF a partir del contenido HTML
        var pdfDocument = renderer.RenderHtmlAsPdf(options.HtmlContent);
        //  Opcional: Aquí, puede utilizar options.Metadata de alguna manera, dependiendo de su tipo genérico T.
        //  Para simplificar, sólo imprimiremos los metadatos en la consola si son de tipo cadena.
        if (options.Metadata is string metadataString)
        {
            Console.WriteLine($"Metadata: {metadataString}");
        }
        //  Guardar el PDF en un archivo
        var fileName = $"GeneratedPdf_{DateTime.Now.Ticks}.pdf";
        pdfDocument.SaveAs(fileName);
        Console.WriteLine($"PDF generated and saved as {fileName}");
    }
}
Public Module PdfGenerator
	Public Sub GeneratePdf(Of T)(ByVal options As PdfOptions(Of T))
		'  Inicializar el renderizador IronPDF HtmlToPdf
		Dim renderer = New ChromePdfRenderer()
		'  Opcional: Aplique aquí cualquier opción del renderizador. Por ejemplo, establecer el tamaño del papel.
		renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4
		'  Generar el PDF a partir del contenido HTML
		Dim pdfDocument = renderer.RenderHtmlAsPdf(options.HtmlContent)
		'  Opcional: Aquí, puede utilizar options.Metadata de alguna manera, dependiendo de su tipo genérico T.
		'  Para simplificar, sólo imprimiremos los metadatos en la consola si son de tipo cadena.
		Dim tempVar As Boolean = TypeOf options.Metadata Is String
		Dim metadataString As String = If(tempVar, CStr(options.Metadata), Nothing)
		If tempVar Then
			Console.WriteLine($"Metadata: {metadataString}")
		End If
		'  Guardar el PDF en un archivo
		Dim fileName = $"GeneratedPdf_{DateTime.Now.Ticks}.pdf"
		pdfDocument.SaveAs(fileName)
		Console.WriteLine($"PDF generated and saved as {fileName}")
	End Sub
End Module
VB   C#

Por último, vamos a utilizar nuestra clase PdfGenerator para generar un documento PDF. En este ejemplo, la propiedad Metadatos podría ser una cadena que contenga un título o cualquier otra información que considere relevante.

class Program
{
    static void Main(string [] args)
    {
        License.LicenseKey = "License-Key";
        var options = new PdfOptions<string>
        {
            HtmlContent = "<h1>Hello, World!</h1><p>This is a test PDF document generated from HTML.</p>",
            Metadata = "Test PDF Title"
        };
        PdfGenerator.GeneratePdf(options);
    }
}
class Program
{
    static void Main(string [] args)
    {
        License.LicenseKey = "License-Key";
        var options = new PdfOptions<string>
        {
            HtmlContent = "<h1>Hello, World!</h1><p>This is a test PDF document generated from HTML.</p>",
            Metadata = "Test PDF Title"
        };
        PdfGenerator.GeneratePdf(options);
    }
}
Friend Class Program
	Shared Sub Main(ByVal args() As String)
		License.LicenseKey = "License-Key"
		Dim options = New PdfOptions(Of String) With {
			.HtmlContent = "<h1>Hello, World!</h1><p>This is a test PDF document generated from HTML.</p>",
			.Metadata = "Test PDF Title"
		}
		PdfGenerator.GeneratePdf(options)
	End Sub
End Class
VB   C#

Este ejemplo ilustra los fundamentos de la integración de IronPDF con C# Generics, proporcionando una forma flexible de generar PDFs a partir de contenido HTML al tiempo que permite metadatos personalizables o configuraciones a través del genérico PdfOptionsclase. Puede ampliarlo añadiendo opciones más sofisticadas y configuraciones del renderizador según las necesidades de su aplicación.

C# Genéricos (Cómo funciona para los desarrolladores): Figura 1 - Ejemplo de salida de código utilizando generics para crear un documento PDF a partir de una cadena HTML utilizando IronPDF

Conclusión

C# Genéricos (Cómo funciona para los desarrolladores): Figura 2 - Página de licencias de IronPDF

Los genéricos de C# son una potente herramienta para desarrollar código de alta calidad, reutilizable y seguro desde el punto de vista tipográfico. Al comprender y aplicar clases, métodos, interfaces y delegados genéricos, puede escribir código más adaptable y fácil de mantener. Los genéricos no sólo permiten la reutilización del código en distintos tipos de datos, sino que también garantizan la comprobación de tipos en tiempo de compilación, lo que reduce los errores en tiempo de ejecución y mejora la calidad general del código. IronPDF ofrece un prueba gratuita cuesta $749 en adelante.

< ANTERIOR
C# String.Join (Cómo funciona para desarrolladores)
SIGUIENTE >
Palabra clave virtual en C# (Cómo funciona para los desarrolladores)

¿Listo para empezar? Versión: 2024.7 recién publicada

Descarga gratuita de NuGet Descargas totales: 9,974,197 Ver licencias >
123