AYUDA .NET

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

Kannaopat Udonpant
Kannapat Udonpant
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. Utilizandogenéricospuede 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 yFunciones de la biblioteca IronPDF para la manipulación de PDF.

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; } }
}

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");

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;
    }
}

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);

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();
}

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);

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");

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;
    }
}

IronPDF: Biblioteca PDF C

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 engenerar PDF a partir de HTMLedició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; }
}

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)
    {
        // Initialize the IronPDF HtmlToPdf renderer
        var renderer = new ChromePdfRenderer();
        // Optional: Apply any renderer options here. For example, setting the paper size.
        renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
        // Generate the PDF from HTML content
        var pdfDocument = renderer.RenderHtmlAsPdf(options.HtmlContent);
        // Optional: Here, you can use options.Metadata in some way, depending on your generic type T.
        // For simplicity, we're just printing the metadata to console if it's of type string.
        if (options.Metadata is string metadataString)
        {
            Console.WriteLine($"Metadata: {metadataString}");
        }
        // Save the PDF to a file
        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)
    {
        // Initialize the IronPDF HtmlToPdf renderer
        var renderer = new ChromePdfRenderer();
        // Optional: Apply any renderer options here. For example, setting the paper size.
        renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
        // Generate the PDF from HTML content
        var pdfDocument = renderer.RenderHtmlAsPdf(options.HtmlContent);
        // Optional: Here, you can use options.Metadata in some way, depending on your generic type T.
        // For simplicity, we're just printing the metadata to console if it's of type string.
        if (options.Metadata is string metadataString)
        {
            Console.WriteLine($"Metadata: {metadataString}");
        }
        // Save the PDF to a file
        var fileName = $"GeneratedPdf_{DateTime.Now.Ticks}.pdf";
        pdfDocument.SaveAs(fileName);
        Console.WriteLine($"PDF generated and saved as {fileName}");
    }
}

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);
    }
}

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, podrá 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 unprueba gratuita de sus herramientas de biblioteca PDFcon costes a partir de $749.

Kannaopat Udonpant
Ingeniero de software
Antes de convertirse en ingeniero de software, Kannapat realizó un doctorado en Recursos Medioambientales en la Universidad de Hokkaido (Japón). Mientras cursaba su licenciatura, Kannapat también se convirtió en miembro del Laboratorio de Robótica Vehicular, que forma parte del Departamento de Ingeniería de Bioproducción. En 2022, aprovechó sus conocimientos de C# para unirse al equipo de ingeniería de Iron Software, donde se centra en IronPDF. Kannapat valora su trabajo porque aprende directamente del desarrollador que escribe la mayor parte del código utilizado en IronPDF. Además del aprendizaje entre iguales, Kannapat disfruta del aspecto social de trabajar en Iron Software. Cuando no está escribiendo código o documentación, Kannapat suele jugar con su PS5 o volver a ver The Last of Us.
< ANTERIOR
C# String.Join (Cómo funciona para desarrolladores)
SIGUIENTE >
Palabra clave virtual en C# (Cómo funciona para los desarrolladores)