Aprende a eliminar elementos de una lista en C# con precisión y buenas prácticas. Verás cómo borrar por referencia, comprender el rol de getHashCode para que el framework identifique el objeto, y aplicar criterios con predicate y delegados para remover múltiples coincidencias de forma segura.
¿Cómo remover por referencia y verificar el resultado?
Borrar por referencia es directo: pasas el objeto exacto que agregaste a la colección y el framework lo localiza y lo elimina.
Crear un curso temporal con datos claros.
Adicionar a la colección de cursos.
Imprimir antes y después para validar el cambio.
var cursoTemporal =newCurso{ Nombre ="101 vacacional", Jornada = Jornada.Noche
};escuela.Cursos.Adicionar(cursoTemporal);Console.WriteLine("Antes de remover.");// ... imprimir colecciónescuela.Cursos.Remover(cursoTemporal);Console.WriteLine("Después de remover.");// ... imprimir colección
¿Qué valida la referencia al remover?
Se pasa la misma instancia que se agregó.
El framework compara identidad y elimina la coincidencia.
Es útil cuando conservas la referencia del objeto.
¿Qué pasa si ya no tengo la referencia?
No siempre puedes guardar todas las referencias.
Necesitas otros métodos: por índice, por rango o por criterio.
¿Qué hace getHashCode y por qué el framework encuentra el objeto?
Imprimir el hash del objeto ayuda a entender cómo se localiza internamente. El hash es un entero que sirve como identificador para búsquedas rápidas.
Console.WriteLine($"Hash del curso: {cursoTemporal.GetHashCode()}");
Devuelve un entero: puede ser negativo o positivo de cero coma dos mil millones.
La probabilidad de colisión es mínima, pero existe.
No siempre conviene depender del hash para borrar por criterio.
¿Por qué no usar solo el hash como criterio?
Puede haber colisiones, aunque raras.
No expresa la intención de negocio (por ejemplo, borrar por Nombre).
Mejor usar un criterio declarativo con predicate.
¿Qué otras opciones ofrece remove?
Remover por índice: elimina el elemento en una posición.
Remover por rango: elimina un bloque continuo.
Remover todo por criterio: usa un predicate para decidir qué borrar.
¿Cómo borrar por criterio con predicate y delegados?
Cuando pierdes la referencia del objeto, puedes borrar por condición. Para ello, usa un delegado tipo Predicate<Curso> que reciba un Curso y devuelva bool.
// Definir el algoritmo como método (convención: mayúscula inicial en métodos)boolPredicado(Curso curso)=> curso.Nombre =="301";// "trescientos uno"// Encapsular el algoritmo en un delegadoa.Predicate<Curso> miAlgoritmo = Predicado;// Remover todos los cursos cuyo nombre sea "301"escuela.Cursos.RemoveAll(miAlgoritmo);
Esto es encapsulación de algoritmos: pasas “qué borrar” como función.
El delegado garantiza la firma correcta: entrada Curso, salida bool.
El elemento que devuelva true se borra; false se conserva.
¿Cómo asegura un delegado la firma del método?
Un delegado especifica tipos de entrada y salida. Si no coinciden, no compila.
// Ejemplo que NO cumple: devuelve int en lugar de boolintPredicadoMalHecho(Curso curso){return301;// Error: la firma no coincide con Predicate<Curso>}// Ejemplo que cumple: devuelve bool y recibe CursoboolPredicadoBien(Curso curso){return curso.Nombre =="301";}
Evita pasar “cualquier función” que rompa el algoritmo.
Mejora la seguridad y claridad del código.
¿Qué ventajas tiene remover por criterio?
Expresa reglas de negocio: por nombre, jornada u otros campos.
Evita depender de referencias perdidas.
Facilita pruebas: el criterio es una función aislada.
¿Te gustaría ver formas más limpias de escribir el algoritmo con expresiones y funciones en línea? Deja tus preguntas y comenta qué criterio de borrado necesitas modelar.
Para mi es más fácil entender algo si se descompone en partes más sencillas. La definición de delegado es la siguiente: ** lo que se afirma o se niega de un sujeto en una proposición.**
Llevado esto a programación quiere decir que va a ver ++algo++, en este caso es un método que me va a definir si mi sujeto (el curso 301) es el que quiero borrar de una lista (en este caso la lista de cursos)
Para lo anterior se usa un delegado (delegar es cambiar la responsabilidad de algo a alguien) ya que el método no va a saber por si solo qué va a removerse, por ello se delega a nosotros la responsabilidad de eliminar ese curso, y, para hacerse esto efectivo el delegado nos dice "ey, para que yo le borre un curso, usted me tiene que decir si es o no es lo que está en la lista"
:thumbs
ENTENDIDO
Buenos días, hago este aporte dado que me iba resultando un poco complicado entender el tema de la utilización del metodo RemoveAll(Predicado) y el tema de delegados, a mi parecer se cruzaron dos temas al tiempo y me lo hizo mas complicado, comparto ésto por si a alguien más le paso:
Utilización de RemoveAll para una colección:
//Función Predicado encargada de devolver TRUE o FALSE cuando el elemento de la colección cumpla con una condición, luego se eliminará.privatestatic bool predicado(curso obj){return obj.Nombre=="Quinto 3";}//RemoveAll => requiere de la definición de un método que evalué las condiciones de eliminaciónEscuela.cCursos.RemoveAll(predicado);
Delegados: Especifican que parámetros de Entrada y de Salida debe tener una función, Ejemplo (Pasos):
a. Definición del delegado:
//PablaClave<tipoDatoEntrada> nomDelegado = metodoDelDelegado;
Predicate<string> isUpper = IsUpperCase;
b. Definición del método que solo retorna TRUE or FALSE => Evalúa una condición
static bool IsUpperCase(string str){
return str.Equals(str.ToUpper());
}
c. Uso del delegado, result será igual a true dado que es un String el parámetro pasado:
bool result =isUpper("hello world!!");
Saludos.
Puede utilizar una expresión lambda de tal forma hacer su código más compacto y con mayor claridad.
Lo probé y funciono muy bien, me acorde de la función find() de JavaScript.
Es un poco Confuso el uso del predicado en este contexto
Él coloca nombra predicado a una función, podria haberse llamado CursosTerceroPrimaria, despues la funcion removeall, llama a esa función y elimina los seleccionados.
Podría considerarse como en lo que en Javascript se conoce Callback
Espero sus correcciones :
Predicado : Es una función en la cual se define una condición bajo la cual se va remover cierto objeto de una colección.
Delegado : Especifica que parámetros de entrada tiene una función , así mismo que se debe obtener en la misma (Salida).
En este contexto lo que dices de predicado es cierto a medias.
El delegado devuelve un valor booleano en determinada situación.
Es decir, en el caso de la colección si la condición de "Nombre = 301" es verdadera, devuelve un parámetro "true" y esto aunado con la función RemoveAll permite:
1.- Recorrer la lista completa.
2.- El delegado valida si es cierta o no la comparación.
3.- Remueve el objeto de la lista que concuerda con la comparación.
Veamos más a fondo esto:
Si yo hiciera manualmente lo que hace el delegado y la función RemoveAll.
Podría recorrer la lista con un foreach y después acceder al atributo curso.nombre y desde ahí validar si es igual a "301".
El delegado permite hacer comparaciones dentro de funciones.
En el caso del predicado es simplemente validar una función, como dijo Juan Carlos, "encapsulamiento de algoritmos", tal cual.
Si tu función recibe un int y no le estás proporcionando un int entonces hay algo mal, encapsularlo protege de este tipo de errores.
Como un Try Catch pero no de esa forma.
**Predicate<T> **es una construcción funcional que proporciona una manera conveniente de probar básicamente si algo es cierto de un objeto T dado.
Voy a dejar este curso hasta aquí, la verdad muy confuso desde el inicio, el usar variables muy parecidas como Escuela y escuela o Cursos y cursos es muy confuso
Todo un Predicamento
… lo que se da cerca del minuto 6:45 es un claro ejemplo 🤪 de por lo que pasamos los desarrolladores en la soledad de nuestro predicamento vocacional frente a una pantalla y un teclado en esas largas horas de madrugada … ayuda tener cerca un rubber duck con quien charlar y aclarar nuestros algoritmos e implementaciones y en muchas ocasiones nos hablará al oído con la respuesta de ese punto-y-coma faltante en la línea 254 del archivo con 100 líneas de código, pero sí … #hastaEnLasMejoresFamilias 💚 jajajaj
He aquí mis notitas de la clase:
para lo del predicado yo lo entendí así:
la condición es "si el curso es del turno de la mañana(TiposTurno.Mañana), bórralo"
el predicado recorre los elementos de la colección y en mi caso el curso "101" y "102" son de la mañana y devuelve un valor "true"
y ya uniendo RemoveAll ** con el predicado, este borra todo lo que tenga el turno de la mañana == true**
espero haberme explicado bien :)