03/10/26 · 7 min de lectura

Listas y Diccionarios en C#

Cómo crear y utilizar las colecciones de listas y diccionarios.

Imagen por Logan Voss .

Ambos funcionan de manera similar a los arreglos o arrays pero con algunas diferencias importantes. Vamos a echarle un vistazo a la clase List primero.

Una lista es como un arreglo que cambia de tamaño dinámicamente. Esto significa que no necesitas saber cuántos elementos va a tener por adelantado. Antes de entrar en materia vamos a crear una clase rápidamente que podamos ordenar en nuestra List.

Desde que una lista es genérica puede guardar cualquier tipo. Pero para nuestro ejemplo, vamos a crear una clase llamada BadGuy. De esta manera, podemos tener una lista de todos los BadGuy. Esta clase no tendrá herencia, pero sí dos campos públicos llamados name y power, y un constructor para asignar estos valores.

public class BadGuy 
{
    public string name;
    public int power;

    public BadGuy(string newName, int newPower)
    {
        name = newName;
        power = newPower;
    }
}

Ahora podemos empezar a hacer nuestra List (lista). Lo primero que se debe hacer cuando se hace una lista es incluir el namespace System.CollectionsGeneric vamos a hacerlo en la parte superior del script.

Luego declaramos List. Esta es una clase genérica, entonces ponemos el nombre de la clase después de cualquier modificador, seguido por un tipo que querramos guardar en la lista. En nuestro caso, BadGuy. Luego le damos un nombre a la lista y dado que List es una clase invocamos un constructor.

using UnityEngine;
using System.Collections.Generic;

public class SomeClass : MonoBehaviour 
{
    void Start()
    {
        List<BadGuy> badGuys = new List<BadGuy>();
    }
}

Actualmente, nuestra lista está vacía; entonces, vamos a asignarle cosas. Para hacerlo usamos la función Add(). Esto agregará un elemento nuevo al final de la lista. El parámetro para la función Add() es el objeto que se está agregando a la lista. En nuestro caso, vamos a invocar un constructor para la clase BadGuy. Ahora, vamos a poblar la lista.

using UnityEngine;
using System.Collections.Generic;

public class SomeClass : MonoBehaviour 
{
    void Start()
    {
        List<BadGuy> badGuys = new List<BadGuy>();

        badGuys.Add(new BadGuy("Harvey", 50));
        badGuys.Add(new BadGuy("MAgneto", 100));
        badGuys.Add(new BadGuy("Pip", 5));
    }
}

Los elementos en una lista pueden accederse de la misma manera que un arreglo o array, usando un índice. También tiene una propiedad count, la misma que funciona de la misma manera que la propiedad Length de los arrays (arreglos).

Las listas tienen funciones como RemoveAt() e Insert() para organización manual.

RemoveAt()elimina un elemento de la lista en un índice determinado y mueve todos los elementos que están delante suyo un puesto hacia adelante.

badGuys.RemoveAt(0);

Insert() toma un índice y un elemento, empujando cada elemento después de cada índice hacia arriba un puerto.

badGuys.Insert(0, new BadGuy("keiko", 999));

Una de las funciones más poderosas de una lista es Sort(). Esta se puede usar para ordenar una lista de un tipo determinado por cualquier variable de ese tipo. Depende del tipo que implementa la interfaz IComparable. Regresemos a nuestra clase BadGuy e implementémosla.

Primero, IComparable está en el namespace System; por lo tanto necesitamos declarar que estamos usándolo. Luego, necesitamos decirle que esta clase está implementando la interfaz. Esto se parece a la herencia. Vamos a usar el genérico IComparable y su tipo genérico necesita estar en esta clase. Por último, para completar el contrato de la interfaz IComparable necesitamos declarar una función pública llamada CompareTo, la misma que regresa un entero y toma nuestro tipo genérico, BadGuy, como un parámetro.

public interface IComparable
{
    void CompareTo(T other);
}

public class BadGuy, IComparable<BadGuy>
{
    public string name;
    public int power;

    public BadGuy(string newName, int newPower)
    {
        name = newName;
        power = newPower;
    }

    public int CompareTo(BadGuy other)
    {
    }
}

La idea detrás del método CompareTo es que el objeto del que se invoca es mayor que el objeto que se toma como parámetro, entonces la función regresa un positivo. Si el objeto del que se invoca el método es menor que el objeto que se toma como parámetro, entonces la función regresa un negativo. Y si son iguales, la función regresa un 0.

public int CompareTo(BadGuy other)
{
    if(other == null)
    {
        return 1;
    }

    return power - other.power;
}

Por lo tanto, regresará un positivo si el método BadGuy del que se invoca es mayor. Ten en cuenta que podríamos haber basado este resultado en cualquier cosa. La interfaz solo requiere que implementemos el método.

Ahora para organizar la lista usando esta comparación, invocamos badguys.Sort(). Vamos a registrar la lista de BadGuy a la consola para mostrar que han sido ordenados.

badGuys.Sort();

foreach(BadGuy guy in badGuys)
{
    print(guy.name + " " + guy.power);
}

Para empezar la lista de nuevo y eliminar todos los elementos usa la función Clear() (despejar).

badGuys.Clear();

Estas no son todas las funciones de la clase List. Cubrirlo todo está fuera del enfoque de este blog. Para obtener más información, por favor consulta la información relacionada vinculada abajo.

Los diccionarios funcionan de manera similar a las listas, pero tiene dos tipos. Esto significa que cada elemento constituye un Key Value Pair. (par clave-valor), que también se conoce por sus siglas KVP.

Los diccionarios también se diferencian de las lista en su propósito. Una lista se usa generalmente en vez de un arreglo donde se necesita más flexibilidad o funcionalidad. Un diccionario se usa como una colección de valores que pueden accederse por una o más keys.

El proceso para declarar un Dictionary es muy similar al que se sigue para declarar una List. Primero, incluye el espacio de nombre System.Collections.Generic Luego, declara una variable igual que antes, pero con dos tipos genéricos. El primer tipo es la clave o key Este es el tipo que sirve de referencia para acceder al segundo tipo, el cual es el valor.

using UnityEngine;
using System.Collections.Generic;

public class SomeOtherClass : MonoBehaviour
{
    void Start()
    {
        Dictionary<string, BadGuy> badGuys = new Dictionary<string, BadGuy>();
    }
}

En nuestro ejemplo, tenemos un tipo string para la clave, y un valor de tipo BadGuy. Estamos usando este diccionario para guardar palabras de búsqueda diferentes que puedan usarse para identificar BadGuys específicos.

En nuestro método Start(), declaramos dos BadGuys. Luego los agregamos al Diccionario, al igual que lo hicimos con la lista. Solo que esta vez estamos agregando datos para ambos la key (clave) y el value (valor).

using UnityEngine;
using System.Collections.Generic;

public class SomeOtherClass : MonoBehaviour
{
    void Start()
    {
        Dictionary<string, BadGuy> badGuys = new Dictionary<string, BadGuy>();

        BadGuy bgHarvey = new BadGuy("Harvey", 50);
        BadGuy bgMagneto = new BadGuy("Magneto", 100);

        badGuys.Add("gangster", bgHarvey);
        badGuys.Add("mutant", bgMagneto);
    }
}

Acceder a los valores que se refieran a una clave se realiza de manera similar a acceder a los elementos de un arreglo o una lista. Sin embargo, en vez de usar un índice, que no tiene ningún significado inherente para un diccionario, insertamos una clave dentro de los corchetes.

BadGuy mutant = badGuys["mutant"];
Debug.Log(mutant);

En este ejemplo, insertamos un string y tenemos el retorno correspondiente, BadGuy.

Si se provee una clave, pero tal clave no existe en el diccionario, va a lanzar una excepción. Por lo tanto, si no hay garantía de que la clave exista, es mejor usar el método TryGetValue().

if(badGuys.TryGetValue("birds", out temp))
{
    // success
}
else
{
    // failure
}

Este método tiene un parámetro del tipo de la clave y un parámetro out del tipo del valor. Regresa true o verdadero si la clave pasada en el primer parámetro existe, Mientras que este es un método más seguro para regresar un valor de un diccionario, es un poco más lento que hacer una referencia directa a la clave específica.

Para ser más eficiente, usa la clave dentro de los corchetes, pero solo cuando la clave específica está definitivamente en el diccionario.

Gist del proyecto

Apoya el contenido de mi blog a través de:

Fuente:

Copiado!