Els genèrics són una característica poderosa de C# que permeten definir classes, mètodes i estructures amb un tipus de dades genèric. Això permet que el codi sigui més flexible i reutilitzable, ja que es pot treballar amb diferents tipus de dades sense duplicar el codi.

Conceptes Clau

  1. Definició de Genèrics: Els genèrics permeten crear classes, mètodes, interfícies i delegats que poden treballar amb qualsevol tipus de dades.
  2. Paràmetres de Tipus: Els genèrics utilitzen paràmetres de tipus per especificar el tipus de dades amb el qual treballaran.
  3. Restriccions de Tipus: Es poden aplicar restriccions als paràmetres de tipus per limitar els tipus de dades que es poden utilitzar.

Avantatges dels Genèrics

  • Reutilització del Codi: Permeten escriure codi que pot treballar amb qualsevol tipus de dades.
  • Seguretat de Tipus: Proporcionen seguretat de tipus en temps de compilació, evitant errors de tipus en temps d'execució.
  • Rendiment: Milloren el rendiment en comparació amb l'ús de tipus objecte, ja que eviten la necessitat de conversions de tipus (boxing/unboxing).

Exemples Pràctics

Exemple 1: Classe Genèrica

// Definició d'una classe genèrica
public class Caixa<T>
{
    private T contingut;

    public void Afegir(T element)
    {
        contingut = element;
    }

    public T Obtenir()
    {
        return contingut;
    }
}

// Ús de la classe genèrica
public class Programa
{
    public static void Main()
    {
        Caixa<int> caixaEnter = new Caixa<int>();
        caixaEnter.Afegir(123);
        Console.WriteLine(caixaEnter.Obtenir()); // Sortida: 123

        Caixa<string> caixaString = new Caixa<string>();
        caixaString.Afegir("Hola, món!");
        Console.WriteLine(caixaString.Obtenir()); // Sortida: Hola, món!
    }
}

Exemple 2: Mètode Genèric

// Definició d'un mètode genèric
public class Utilitats
{
    public static void Intercanviar<T>(ref T a, ref T b)
    {
        T temp = a;
        a = b;
        b = temp;
    }
}

// Ús del mètode genèric
public class Programa
{
    public static void Main()
    {
        int x = 1, y = 2;
        Utilitats.Intercanviar(ref x, ref y);
        Console.WriteLine($"x: {x}, y: {y}"); // Sortida: x: 2, y: 1

        string s1 = "Hola", s2 = "Adéu";
        Utilitats.Intercanviar(ref s1, ref s2);
        Console.WriteLine($"s1: {s1}, s2: {s2}"); // Sortida: s1: Adéu, s2: Hola
    }
}

Exemple 3: Restriccions de Tipus

// Definició d'una classe genèrica amb restriccions de tipus
public class Comparador<T> where T : IComparable<T>
{
    public T Max(T a, T b)
    {
        return a.CompareTo(b) > 0 ? a : b;
    }
}

// Ús de la classe genèrica amb restriccions de tipus
public class Programa
{
    public static void Main()
    {
        Comparador<int> comparadorEnter = new Comparador<int>();
        Console.WriteLine(comparadorEnter.Max(3, 7)); // Sortida: 7

        Comparador<string> comparadorString = new Comparador<string>();
        Console.WriteLine(comparadorString.Max("poma", "plàtan")); // Sortida: plàtan
    }
}

Exercicis Pràctics

Exercici 1: Classe Genèrica de Pila

Crea una classe genèrica Pila<T> que implementi les operacions bàsiques d'una pila (push, pop, peek).

Solució

public class Pila<T>
{
    private List<T> elements = new List<T>();

    public void Push(T element)
    {
        elements.Add(element);
    }

    public T Pop()
    {
        if (elements.Count == 0)
            throw new InvalidOperationException("La pila està buida.");
        
        T element = elements[elements.Count - 1];
        elements.RemoveAt(elements.Count - 1);
        return element;
    }

    public T Peek()
    {
        if (elements.Count == 0)
            throw new InvalidOperationException("La pila està buida.");
        
        return elements[elements.Count - 1];
    }

    public int Count => elements.Count;
}

// Ús de la classe genèrica Pila
public class Programa
{
    public static void Main()
    {
        Pila<int> pilaEnter = new Pila<int>();
        pilaEnter.Push(1);
        pilaEnter.Push(2);
        pilaEnter.Push(3);
        Console.WriteLine(pilaEnter.Pop()); // Sortida: 3
        Console.WriteLine(pilaEnter.Peek()); // Sortida: 2
        Console.WriteLine(pilaEnter.Count); // Sortida: 2
    }
}

Exercici 2: Mètode Genèric de Cerca

Crea un mètode genèric Cerca<T> que busqui un element en una llista i retorni la seva posició.

Solució

public class Utilitats
{
    public static int Cerca<T>(List<T> llista, T element)
    {
        for (int i = 0; i < llista.Count; i++)
        {
            if (llista[i].Equals(element))
                return i;
        }
        return -1; // Retorna -1 si l'element no es troba
    }
}

// Ús del mètode genèric Cerca
public class Programa
{
    public static void Main()
    {
        List<int> llistaEnter = new List<int> { 1, 2, 3, 4, 5 };
        Console.WriteLine(Utilitats.Cerca(llistaEnter, 3)); // Sortida: 2

        List<string> llistaString = new List<string> { "poma", "plàtan", "taronja" };
        Console.WriteLine(Utilitats.Cerca(llistaString, "plàtan")); // Sortida: 1
    }
}

Resum

En aquesta secció, hem après sobre els genèrics en C#, incloent-hi la seva definició, avantatges i com utilitzar-los en classes i mètodes. També hem vist com aplicar restriccions de tipus per limitar els tipus de dades que es poden utilitzar amb genèrics. Els exercicis pràctics proporcionats ajuden a reforçar aquests conceptes i a veure com es poden aplicar en situacions reals. En la següent secció, explorarem les col·leccions genèriques i com utilitzar-les per gestionar dades de manera eficient.

© Copyright 2024. Tots els drets reservats