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
- Definició de Genèrics: Els genèrics permeten crear classes, mètodes, interfícies i delegats que poden treballar amb qualsevol tipus de dades.
 - Paràmetres de Tipus: Els genèrics utilitzen paràmetres de tipus per especificar el tipus de dades amb el qual treballaran.
 - 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.
Curs de Programació en C#
Mòdul 1: Introducció al C#
- Introducció al C#
 - Configuració de l'Entorn de Desenvolupament
 - Programa Hello World
 - Sintaxi i Estructura Bàsica
 - Variables i Tipus de Dades
 
Mòdul 2: Estructures de Control
Mòdul 3: Programació Orientada a Objectes
Mòdul 4: Conceptes Avançats de C#
- Interfícies
 - Delegats i Esdeveniments
 - Genèrics
 - Col·leccions
 - LINQ (Consulta Integrada al Llenguatge)
 - Programació Asíncrona
 
Mòdul 5: Treballant amb Dades
Mòdul 6: Temes Avançats
- Reflexió
 - Atributs
 - Programació Dinàmica
 - Gestió de Memòria i Recollida d'Escombraries
 - Multifil i Programació Paral·lela
 
Mòdul 7: Construcció d'Aplicacions
Mòdul 8: Millors Pràctiques i Patrons de Disseny
- Estàndards de Codificació i Millors Pràctiques
 - Patrons de Disseny
 - Proves Unitàries
 - Revisió de Codi i Refactorització
 
