Aprende a escribir código más claro y compacto en C# al trabajar con colecciones: de predicados tradicionales a delegados y expresiones lambda, con ejemplos prácticos de borrado con RemoveAll y buenas prácticas de comentarios en Visual Studio Code. Confianza y eficiencia en un solo lugar.
¿Cómo simplificar el borrado en colecciones con predicados y RemoveAll?
Trabajar con colecciones genéricas requiere decisiones claras para agregar y remover elementos. Aquí se muestra cómo pasar de un predicado explícito a formas más limpias y mantenibles.
Predicado como método: un método que recibe un Curso y devuelve bool.
// Basado en un método predicadoboolEsNombre301(Curso curso)=> curso.Nombre =="301";cursos.RemoveAll(EsNombre301);// Elimina todos con Nombre == "301".
Inferencia de tipos: desde C# 3.5 el compilador infiere el tipo del predicado al pasarlo como argumento, evitando “mappings” innecesarios.
Remoción múltiple: RemoveAll recorre la colección; elimina los que devuelven true y deja los que devuelven false.
¿Cómo reescribir con delegate para mayor claridad?
Cuando el predicado es corto, puedes definir el delegado en línea. Es legible y explícito.
// Delegado anónimo dentro de RemoveAllcursos.RemoveAll(delegate(Curso cur){return cur.Nombre =="301";});
Ventaja: encapsulas la lógica sin declarar un método aparte.
Consideración: en el delegado anónimo especifica el tipo del parámetro.
¿Cómo compactar con una expresión lambda?
La forma más concisa para condiciones simples: menos código, misma intención.
// Lambda expression, tipo inferido por la lista genéricacursos.RemoveAll(cur => cur.Nombre =="301");
Lectura directa: para cada cur, evalúa la condición y elimina si es true.
Sin tipo explícito: el compilador infiere Curso desde List<Curso>.
¿Cómo aplicar condiciones compuestas?
Cuando hay duplicados o múltiples criterios, combina condiciones lógicas.
// Eliminar todos los "501"cursos.RemoveAll(cur => cur.Nombre =="501");// Eliminar solo "501" en jornada mañanacursos.RemoveAll(cur => cur.Nombre =="501"&& cur.Jornada == TipoJornada.JornadaManana);
Bool en acción: el tipo bool es clave para filtrar en colecciones.
Criterios flexibles: combina campos como Nombre y Jornada.
¿Qué formas de comentarios usar en C# según el contexto?
Comentar bien acelera el mantenimiento y la colaboración. Usa el estilo adecuado para cada necesidad.
¿Cuándo usar comentarios de una línea y multilínea?
Una línea con doble slash para notas breves.
// Esto elimina cursos con Nombre == "301".
Multilínea para bloques más extensos.
/*
Bloque de comentarios.
Útil para desactivar secciones de código temporalmente.
*/
Atajos en Visual Studio Code:
Ctrl + K, C: poner comentarios.
Ctrl + K, U: quitar comentarios.
¿Cómo documentar métodos con comentarios XML?
Para documentación formal y autogenerada, usa triple slash.
/// <summary>/// Imprime la lista de cursos en consola./// </summary>/// <paramname="cursos">colección a imprimir.</param>voidImprimirCursos(List<Curso> cursos){/* ... */}
Ideal para proyectos profesionales.
Compatible con herramientas del ecosistema .NET.
¿Qué habilidades y conceptos clave refuerzas al practicar esto?
Al aplicar estas técnicas, mejoras tu dominio de colecciones y del modelo de delegados en C#.
Colecciones vs. arreglos: colecciones ofrecen operaciones de alto nivel como RemoveAll.
Predicado: método que recibe un tipo (Curso) y devuelve bool para decidir eliminación.
Delegado: función pasada como parámetro; puede ser método, delegado anónimo o lambda.
Expresión lambda: sintaxis compacta para delegados con inferencia de tipos.
Inferencia de tipos: el compilador deduce tipos desde el contexto genérico.
Bool: base de filtros y decisiones en recorridos.
Comentarios: //, /* */ y /// para control, desactivación de bloques y documentación.
Productividad en editor: atajos de Visual Studio Code para comentar y descomentar.
¿Te gustaría ver variantes con condiciones más complejas o con otros campos del modelo? Comparte tus dudas y casos en los comentarios.
Llevo varios años desarrollando en C# y es primera vez que veo de manera tan sencilla el tema de los delegados, ya he tenido a;os usando expresiones lambda pero ver este paso a paso es muy gratificante.
Empece a ver este curso para fortalecer conceptos básicos y revisar mis conocimiento!
EXCELENTE CURSO!!!
X2
++
Por lo que infiero a partir de esta clase y de lo que he podido leer sobre delegados, entiendo que los delegados son un TIPO en .net cuya PRINCIPAL FUNCIÓN es la de permitir pasar metodos a otros métodos. Estos métodos se puede pasar como Métodos anónimos o como expresiones lambda. Veo que cuando se pasa de la declaración de un delegado al uso de una expresión lambada la cantidad de código se reduce sustancialmente. Sin embargo creo que las expresiones lambda favorecen la programación In LIne, esa que se requiere hacer al paso. Pero si se presentase el caso de necesitar pasar un mismo método como parámetoro a muchos otro métodos si sería más recomendable definir el método a pasar como parámetro en un único lugar del código. Es lo que creo … espero les sirva de algo !!
totalmente de acuerdo
Realmente un delegado no pasa la funcion, es mas bien un apuntador, envía la ubicación en memoria de la función.
Super entendible el curso, considerando que soy programador entrando al mundo de C# para ampliar mis skills. Pero para novatos entrando al mundo de la programación, no lo se Rick…
Yo agradezco al team Platzi de todas formas porque el enfoque con el que entra este curso acelera el aprendizaje de C# para ponerlo a la de ya en la práctica.
Yo creo que esta bien para ambos "Nuevos" y "Experimentados", ya que al hacerlo en la marcha de un proyecto aprendes de manera mas "Empírica" y no "Sistemática".
Se puede instalar el paquete C# XML Documentation Comments, para que automaticamente escribiendo /// sobre el método, esto te construya la sección de documentación de las clases y métodos.
Creo que tambien puede evitar el uso de (). Lo podria resumir a simplemente lo siguiente:
escuela.Cursos.RemoveAll(x => x.Nombre.Equals(“301”));
Usando expresiones Lambda.
Sería bueno que se explicara cuando se debe utilizar el == y el Equals en tipos de datos string, ya que la comparación no es exactamente la misma.
Es verdad, no es necesario esos paréntesis en la expresión. Lo mas común es no usarlos a menos que la expresión tenga mas de un parámetro en el cual se usaría algo como (x,y) => .....
Les recomiendo utilizar la expresion lambda que se usa al final de una vez asi cuando les toque hacer operaciones hacia base de datos usando LinQ van a estar familiarizados y se les hara super facil.
Gracias por la recomendación. Además me parece más fácil de entender.
El video donde da una breve explicación o menciona los delegados esta interesante, sería bueno poder tener más ejemplos de como se implementan o cuando se implementan, ventajas o usos reales que se les da.
Inferencia de tipos : Los inferencia de tipos es una característica predominante de los lenguajes de programación funcionales tales como C#. La inferencia de tipos asigna automáticamente un tipo de datos a una función sin necesidad de que el programador lo escriba.
El profe debio empezar por los comentario ajajaja.
Definición Una expresión lambda es una función o método anónimo con el que podemos crear tipo delegados y árboles de expresiones
Ejemplo de una expresión lamba
<string[] digits ={"zero","one","two","three","four","five","six","seven","eight","nine"};Console.WriteLine("Example that uses a lambda expression:");var shortDigits = digits.Where((digit, index)=> digit.Length< index);foreach(var sD in shortDigits){Console.WriteLine(sD);}>
Podrían explicar las diferencias entre Equals y ==, según cada tipo de dato?
en forma documental no te puedo dar una explicación “científica”, pero en forma practica te puedo comentar que a mi me ha sucedió en sentencias if, si hago la comparación cadena == “SI” hay ocasiones que me lo interpreta bien y otras mal, pero cuando utilizo el cadena.Equals(“SI”) en estos casos el resultado siempre es exacto, no se si tiene algo que ver a nivel de bits, bytes o algo parecido, el problema regularmente se me presenta solamente con variables tipo string, con variables booleanas, numéricas, etc nunca he tenido algún problema parecido
Lo que pasa es que el operador == y el método Equals por defecto verifican si 2 objetos son el mismo (es decir comprar las posiciones de memoria), por ejemplo
va a imprimir False en ambos casos , porque aunque los 2 objetos son creados de a misma forma y con los mismos valores son 2 instancias distindos y por tanto no son iguales.
Lo que pasa con string es que implementa una sobrecarga para el operador == y para el metodo Equals, para que no solo compare si son la misma instancia, si no que hace una compraracion de sus valores, puedes ver mas en esta discucion .
En c# se puede hacer sobrecarga de operadores, entonces puedes cambia la logica que usa el operador == para un objeto en concreto, por eso puede haber casos en los que el operador == y el metodo Equals hagan cosas distintas, para eso te recomiendo leer aí muestran algunos ejemplos de como sobrecargar el operador == y el metodo Equals.
Tambien te recomiendo leer esta pagina, es my corta y te dice en que momentos sobrecargar o l operador o el metodo
Espero que te ayude.
Me marca el siguiente error y no entiendo por qué si tengo el mismo código que el del curso:
El operador '==' no se puede aplicar a operandos del tipo 'string' y 'TiposJornada' [Etapa1]
¿Por que el código del curso no marca error?
Te falta especificar el tipo de jornada.
Ejemplo: TiposJornada.tarde
//Definir un Delegadoescuela.Cursos.RemoveAll(delegate(Curso cur){return cur.Nombre=="301";});//Definir una expresión Lambdaescuela.Cursos.RemoveAll((cur)=> cur.Nombre=="301");
aqui les dejo un resumen de mis apuntes por si les interesa:
Delegados:
<code>public delegate voidMyDelegate(int a, int b);// declaracion del delegado y sus parametros, funciona para cualquier tipo de metodo; un delegado es una funcion que se puede asignar a una variablepublicstaticvoidMain(string[] args){MyDelegate del =newMyDelegate(Add);// se asigna la funcion Add a la variable deldel(10,20); del =newMyDelegate(Subtract);// se asigna la funcion Subtract a la variable deldel(10,20); del =newMyDelegate(Multiply);// se asigna la funcion Multiply a la variable deldel(10,20); del =newMyDelegate(Divide);// se asigna la funcion Divide a la variable deldel(10,20);}publicstaticvoidAdd(int a, int b){Console.WriteLine(a + b);}publicstaticvoidSubtract(int a, int b){Console.WriteLine(a - b);}publicstaticvoidMultiply(int a, int b){Console.WriteLine(a * b);}publicstaticvoidDivide(int a, int b){Console.WriteLine(a / b);}
Lambda:
<code>publicstaticvoidMain(string[] args){List<entry> entries =newList<entry>{newentry{ name ="John", lastname ="Doe"},newentry{ name ="Jane", lastname ="Will"},newentry{ name ="Joe", lastname ="Black"},newentry{ name ="Jack", lastname ="White"},newentry{ name ="Jill", lastname ="Valentine"},newentry{ name ="Juan", lastname ="Perez"},};// Ordena la lista de forma ascendente y es una funcion anonima//===================================================================================================//entries.Sort(compareEntries); //===================================================================================================// ordena la lista de forma descendente y es una funcion anonima//===================================================================================================//entries.Sort(delegate (entry x, entry y) //{// return $"{x.name} {x.lastname}".CompareTo($"{y.name} {y.lastname}");//}//);//===================================================================================================// lambda expresion para ordenar la lista, lambda se utiliza para ordenar una lista de objetos o una lista de entradas//=================================================================================================== entries.Sort((x, y)=> $"{x.name} {x.lastname}".CompareTo($"{y.name} {y.lastname}"));//===================================================================================================// se realiza un foreach para imprimir la lista en consola// ==================================================================================================foreach(entry entry in entries){Console.WriteLine($"{entry.name} {entry.lastname}");}//===================================================================================================Console.ReadKey();// se pone para que no se cierre la consola}//private static int compareEntries(entry e1, entry e2)//{// return $"{e1.name} {e1.lastname}".CompareTo($"{e2.name} {e2.lastname}");//}
Comparto parte del contenido del curso
using System.Runtime.Serialization.Json;// See https://aka.ms/new-console-template for more informationusing CoreEscuela.Entidades;Console.WriteLine("Hello, World!");Escuela es =newEscuela("Escuela Basicas",1995,TiposEscuela.Primaria,ciudad:"Medellin",pais:"Colombia");Curso cursos1 =newCurso();cursos1.Nombre="Pruebas";cursos1.Jornada=TiposJornada.Manaña;var curso2 =newCurso(){Nombre="102",Jornada=TiposJornada.Tarde};var arrayCursos =newCurso[3];arrayCursos[0]=newCurso(){Nombre="301",Jornada=TiposJornada.Noche};var cursos2 =newCurso(){Nombre="302",Jornada=TiposJornada.Noche};arrayCursos[1]= cursos2;arrayCursos[2]=newCurso(){Nombre="303",Jornada=TiposJornada.Noche};var listas1 =newList<Curso>(){newCurso(){Nombre="505"},newCurso(){Nombre="506"},newCurso(){Nombre="507"}};var listas2 =newList<Curso>(){newCurso(){Nombre="401"},newCurso(){Nombre="402"}};listas1.Add(newCurso{Nombre="508"});//es.Cursos.Add(new Curso(){Nombre="401", Jornada = TiposJornada.Manaña});listas1.AddRange(listas2);listas1.RemoveAll(delegate(Curso cur){return cur.Nombre=="402";});listas1.RemoveAll((cur)=> cur.Nombre.Equals("506"));Console.WriteLine(es.Nombres);Console.WriteLine("=======================================");Console.WriteLine(cursos1.Nombre+","+ cursos1.Jornada+","+ cursos1.CursoId);Console.WriteLine($"{curso2.Nombre} , {curso2.Jornada} , {curso2.CursoId}");ImprimirCurosNoche(arrayCursos);Console.WriteLine("========================================");foreach(var list in listas1){Console.WriteLine($"Salon: {list.Nombre} ");}voidImprimirCurosNoche(Curso[] arrayCursos){foreach(var curso in arrayCursos){Console.WriteLine($"Nombre: {curso.Nombre} , Jornada: {curso.Jornada}, Id: {curso.CursoId}");}} output
Hello,World!EscuelaBasicas=======================================Pruebas,Manaña,be479669-8ae6-4e95-9ecd-c9ae4086db3b
102,Tarde,61618250-2e95-4888-bd26-8c14f6d513d0
Nombre:301,Jornada:Noche,Id: d423e6ec-cd6b-476e-b33f-d4223ffb1da7
Nombre:302,Jornada:Noche,Id:85978e34-115f-461f-833f-531a0bf39520
Nombre:303,Jornada:Noche,Id: d446dffc-d8f4-4650-9ddf-b003d5663ca6
========================================Salon:505Salon:506Salon:507Salon:508Salon:401Salon:402PSC:\Users\juand\OneDrive\Documents\Cursos\Net6\FundamentosCore2.1> dotnet run
Hello,World!EscuelaBasicas===============================================================================Salon:505Salon:507Salon:508Salon:401
Esto es muy parecido a la función filter de JavaScript :
Me gusto mucho la manera como el profe explica conceptos complejos
:o no sabia que en C# se podian hacer los arrow function de javascript, me esta gustando mas este curso.
Escribir comentarios a metodos es de gran ayuda ya que luego el propio editor te indica los comentarios que escribiste; no solo para el metodo si no tambien para cada uno de los parametros del mismo.
Por ejemplo:
Comentas este codigo a nivel de metodo:
Y cuando un programador hace uso del ese metodo, aparecerá facilmente la ayuda sobre ese metodo:
Estos comentarios se pueden aplicar a clases, metodos, propiedades, eventos, variables, etc, etc.