Saltar al pie de página
.NET AYUDA

C# Genéricos (Cómo Funciona para Desarrolladores)

Los genéricos de C# introducen una forma de diseñar clases, métodos, interfaces y delegados donde el tipo de datos que gestionan se puede especificar como un parámetro. Este concepto, conocido como un parámetro de tipo genérico, permite la creación de componentes de código flexibles y reutilizables. Al utilizar genéricos, se 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, ofreciendo versatilidad e integridad de tipos. En este artículo, aprenderemos sobre los conceptos básicos de los genéricos de C# y las características de la biblioteca IronPDF para la manipulación de documentos PDF.

Los fundamentos de las clases genéricas

Una clase genérica en C# es un esquema para crear una clase con un marcador de posición para el tipo que contiene o en 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 un parámetro de tipo T para manejar varios tipos de datos. Las clases genéricas son especialmente útiles para las clases de colección, como listas, colas y tablas hash, ya que pueden contener cualquier tipo de dato mientras aseguran la seguridad de tipos y reducen la necesidad de conversiones.

Ejemplo sencillo de una clase genérica

Considere una clase genérica llamada Caja 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; }
    }
}
$vbLabelText   $csharpLabel

Para utilizar esta clase, crea una instancia que especifique el tipo real de 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");
$vbLabelText   $csharpLabel

Este código ilustra cómo una sola clase (Caja) puede adaptarse para almacenar diferentes tipos de datos (int, string), demostrando 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 puedan operar sobre diferentes tipos mientras se definen en una clase que no es genérica o en una clase genérica.

Ejemplo de método genérico

Aquí hay un método que intercambia dos elementos en un array de cualquier tipo:

public class Utility
{
    // Swaps two elements by reference using generics
    public static void Swap<T>(ref T lhs, ref T rhs)
    {
        T temp = lhs; // Store lhs in a temporary variable
        lhs = rhs;    // Assign rhs to lhs
        rhs = temp;   // Assign temp (original lhs) to rhs
    }
}
public class Utility
{
    // Swaps two elements by reference using generics
    public static void Swap<T>(ref T lhs, ref T rhs)
    {
        T temp = lhs; // Store lhs in a temporary variable
        lhs = rhs;    // Assign rhs to lhs
        rhs = temp;   // Assign temp (original lhs) to rhs
    }
}
$vbLabelText   $csharpLabel

El uso del método anterior puede ser como sigue:

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);
$vbLabelText   $csharpLabel

Explorando las interfaces genéricas y los delegados

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

Ejemplo de interfaz genérica

Una interfaz de repositorio genérica para operaciones de acceso a datos podría verse así:

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

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

Ejemplo de delegado genérico

Un delegado genérico podría usarse para definir una devolución de llamada con seguridad de tipo:

public delegate void Action<T>(T item);
public delegate void Action<T>(T item);
$vbLabelText   $csharpLabel

Utilización de colecciones genéricas

Las clases de colección genéricas, como Lista, Diccionario<TKey, TValue>, y otras en el espacio de nombres System.Collections.Generic, ofrecen colecciones eficientes con seguridad de tipo para almacenar y manipular datos de cualquier tipo específico. Estas colecciones son superiores a sus contrapartes no genéricas porque eliminan la necesidad de conversiones y reducen los errores de 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");
$vbLabelText   $csharpLabel

Creación de tipos genéricos personalizados

Más allá de usar los tipos genéricos incorporados, puedes crear los tuyos propios para encapsular operaciones que son comunes a diferentes tipos de datos pero que necesitan ser manejadas de manera específica de tipo. Este enfoque es particularmente útil para construir bibliotecas, frameworks o utilidades que se usarán con varios tipos de datos.

Ejemplo de tipo genérico personalizado

Considere una clase genérica Resultado que encapsula resultados de operaciones junto con un indicador 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;
    }
}
$vbLabelText   $csharpLabel

IronPDF: Biblioteca PDF C

IronPDF es una biblioteca integral diseñada para desarrolladores .NET para crear, editar y extraer documentos PDF dentro de sus aplicaciones. IronPDF ayuda a generar PDFs desde HTML, editar PDFs existentes, convertir PDFs a imágenes, y muchas más funcionalidades. Aunque IronPDF en sí no está basado en genéricos, entender cómo interactuar con esta biblioteca en un entorno de C# puede mejorar enormemente las capacidades de gestión de documentos de tu aplicación.

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

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

Primero, definamos una clase genérica simple que contendrá nuestras opciones de generación de PDF. Con fines de demostración, esta clase será básica, pero se puede ampliar con más propiedades para satisfacer tus 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; }
}
$vbLabelText   $csharpLabel

Ahora, creemos un método estático que genere un PDF utilizando IronPDF, aprovechando nuestra clase PdfOptions. Este método tomará una instancia de PdfOptions como su parámetro, demostrando el uso de genéricos en acción.

using IronPdf; // Make sure to include the necessary namespace for IronPDF

public static class PdfGenerator
{
    // Generates a PDF from provided HTML content and options
    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}");
    }
}
using IronPdf; // Make sure to include the necessary namespace for IronPDF

public static class PdfGenerator
{
    // Generates a PDF from provided HTML content and options
    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}");
    }
}
$vbLabelText   $csharpLabel

Finalmente, usemos nuestra clase GeneradorPdf 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 consideres relevante.

class Program
{
    static void Main(string[] args)
    {
        // Set the license key for IronPDF if needed
        License.LicenseKey = "Your-License-Key-Here";

        // Create PDF options with HTML content and metadata
        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"
        };

        // Generate the PDF using the specified options
        PdfGenerator.GeneratePdf(options);
    }
}
class Program
{
    static void Main(string[] args)
    {
        // Set the license key for IronPDF if needed
        License.LicenseKey = "Your-License-Key-Here";

        // Create PDF options with HTML content and metadata
        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"
        };

        // Generate the PDF using the specified options
        PdfGenerator.GeneratePdf(options);
    }
}
$vbLabelText   $csharpLabel

Este ejemplo ilustra los conceptos básicos de la integración de IronPDF con genéricos de C#, proporcionando una forma flexible de generar PDFs a partir de contenido HTML, mientras permite metadatos o configuraciones personalizables a través de la clase genérica PdfOptions. Puedes expandir esto añadiendo opciones más sofisticadas y configuraciones del renderizador según sea necesario para tu aplicación.

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

Conclusión

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

Los genéricos de C# son una herramienta poderosa para desarrollar código de alta calidad, reutilizable y seguro de tipos. Al comprender y aplicar clases, métodos, interfaces y delegados genéricos, puedes escribir código más adaptable y fácil de mantener. Los genéricos no solo permiten la reutilización de código entre diferentes tipos de datos, sino que también aseguran la verificación de tipos en tiempo de compilación, lo que reduce los errores de tiempo de ejecución y mejora la calidad general del código. IronPDF ofrece una prueba gratuita de sus herramientas de biblioteca PDF, con costos a partir de $799 en adelante.

Preguntas Frecuentes

¿Qué son los genéricos en C#?

Los genéricos en C# introducen una forma de diseñar clases, métodos, interfaces y delegados con un parámetro de tipo. Esto permite la creación de componentes de código flexibles y reutilizables que proporcionan seguridad de tipos y mejoras de rendimiento.

¿Cómo funcionan las clases genéricas en C#?

Una clase genérica en C# utiliza un parámetro de tipo, a menudo denotado como T, que actúa como un marcador de posición para el tipo que contiene u opera. Esto permite que la clase se instancie con varios tipos de datos manteniendo la seguridad de tipos.

¿Puedes dar un ejemplo de una clase genérica en C#?

Sí, un ejemplo simple es una clase Box que almacena un valor de cualquier tipo. Puedes crear instancias como Box o Box para almacenar diferentes tipos de datos usando la misma clase.

¿Qué es un método genérico en C#?

Un método genérico se define con parámetros de tipo a nivel de método, permitiéndole operar sobre diferentes tipos. Puede ser parte de una clase no genérica o genérica, proporcionando flexibilidad en el diseño del método.

¿Cómo se pueden usar interfaces y delegados genéricos en C#?

Las interfaces y delegados genéricos permiten definir contratos y métodos de devolución de llamada que pueden operar con cualquier tipo, mejorando la flexibilidad y la reutilización del código.

¿Cuáles son los beneficios de usar colecciones genéricas en C#?

Las colecciones genéricas como List y Dictionary ofrecen almacenamiento seguro de tipos y eficiente para cualquier tipo específico, eliminando la necesidad de realizar conversiones y reduciendo errores en tiempo de ejecución.

¿Cómo puedo crear tipos genéricos personalizados en C#?

Puedes crear tipos genéricos personalizados para encapsular operaciones comunes a diferentes tipos de datos pero manejadas de manera específica al tipo, útil para construir bibliotecas o utilidades.

¿Cómo pueden los genéricos de C# mejorar la generación de PDF en .NET?

Los genéricos en C# pueden ser utilizados con una biblioteca PDF para crear componentes flexibles y reutilizables. Por ejemplo, una clase PdfOptions puede usarse para mantener opciones de generación de PDF, demostrando la adaptabilidad de los genéricos con tareas de PDF.

¿Cómo puede utilizarse una biblioteca PDF con genéricos en C#?

Una biblioteca PDF, como IronPDF, puede usar genéricos en C# para mejorar su funcionalidad. Por ejemplo, un método genérico podría usarse para convertir HTML a PDF, proporcionando un enfoque flexible para la generación de documentos.

¿Cuáles son las ventajas de usar genéricos en C#?

Los genéricos en C# permiten la reutilización de código en diferentes tipos de datos, aseguran la verificación de tipos en tiempo de compilación, reducen errores de tiempo de ejecución y mejoran la calidad general del código. Permiten escribir código adaptable y mantenible.

Jacob Mellor, Director de Tecnología @ Team Iron
Director de Tecnología

Jacob Mellor es Director de Tecnología en Iron Software y un ingeniero visionario que lidera la tecnología PDF en C#. Como el desarrollador original detrás de la base de código central de Iron Software, ha moldeado la arquitectura de productos de la compañía desde ...

Leer más