vez valores una recorrer obtener net listas lista leer elementos con agregar c# .net vb.net generics collections

c# - valores - recorrer list of t vb net



¿Cuál es la mejor manera de iterar a través de una Lista genérica<T> fuertemente tipada? (7)

Me puede estar perdiendo algo, pero iterar a través de una lista genérica debería ser bastante simple si utiliza mis ejemplos a continuación. La clase List <> implementa las interfaces IList e IEnumerable para que pueda iterar fácilmente a través de ellas básicamente de la forma que desee.

La forma más eficiente sería usar un ciclo for:

for(int i = 0; i < genericList.Count; ++i) { // Loop body }

También puede optar por utilizar un bucle foreach:

foreach(<insertTypeHere> o in genericList) { // Loop body }

¿Cuál es la mejor manera de iterar a través de una lista genérica fuertemente tipada en C # .NET y VB.NET?


Para VB.NET:

For Each tmpObject as ObjectType in ObjectTypeList ''Do some stuff '' Next


Sin conocer la implementación interna de una lista, creo que, en general, la mejor manera de iterar sería un ciclo foreach. Dado que foreach usa un IEnumerator para recorrer la lista, depende de la propia lista determinar cómo moverse de un objeto a otro.

Si la implementación interna fuera, por ejemplo, una lista enlazada, entonces un bucle simple sería bastante más lento que un foreach.

¿Tiene sentido?


Depende de su aplicación:

  • para bucle, si la eficiencia es una prioridad
  • ciclo foreach o método ForEach, lo que comunica su intención más claramente

Para C #:

foreach(ObjectType objectItem in objectTypeList) { // ...do some stuff }

Respuesta para VB.NET de Purple Ant :

For Each objectItem as ObjectType in objectTypeList ''Do some stuff '' Next


DO#

myList<string>().ForEach( delegate(string name) { Console.WriteLine(name); });

Los delegados anónimos no se implementan actualmente en VB.Net, pero tanto C # como VB.Net deberían poder hacer lambdas:

DO#

myList<string>().ForEach(name => Console.WriteLine(name));

VB.Net

myList(Of String)().ForEach(Function(name) Console.WriteLine(name))

Como señaló Grauenwolf, el VB anterior no compilará dado que el lambda no devuelve un valor. Un bucle ForEach normal, como otros lo han sugerido, es probablemente el más fácil por ahora, pero como es habitual, se necesita un bloque de código para hacer lo que C # puede hacer en una línea.

Aquí hay un ejemplo trillado de por qué esto podría ser útil: esto le da la capacidad de pasar la lógica de bucle desde otro ámbito distinto de donde existe el IEnumerable, por lo que ni siquiera tiene que exponerlo si no lo desea.

Supongamos que tiene una lista de rutas de URL relativas que quiere que sean absolutas:

public IEnumerable<String> Paths(Func<String> formatter) { List<String> paths = new List<String>() { "/about", "/contact", "/services" }; return paths.ForEach(formatter); }

Entonces puedes llamar a la función de esta manera:

var hostname = "myhost.com"; var formatter = f => String.Format("http://{0}{1}", hostname, f); IEnumerable<String> absolutePaths = Paths(formatter);

Te doy "http://myhost.com/about", "http://myhost.com/contact" etc. Obviamente hay mejores formas de lograr esto en este ejemplo específico, solo estoy tratando de demostrar el principio básico .


Con cualquier implementación genérica de IEnumerable, la mejor manera es:

//C# foreach( var item in listVariable) { //do stuff }

Sin embargo, hay una excepción importante. IEnumerable implica una sobrecarga de Current () y MoveNext () que es en lo que se compila realmente el bucle foreach.

Cuando tienes una matriz simple de estructuras:

//C# int[] valueTypeArray; for(int i=0; i < valueTypeArray.Length; ++i) { int item = valueTypeArray[i]; //do stuff }

Es mas rapido

Actualizar

Tras una discusión con @Steven Sudit (ver comentarios), creo que mi consejo original puede estar desactualizado o equivocado, así que realicé algunas pruebas:

// create a list to test with var theList = Enumerable.Range(0, 100000000).ToList(); // time foreach var sw = Stopwatch.StartNew(); foreach (var item in theList) { int inLoop = item; } Console.WriteLine("list foreach: " + sw.Elapsed.ToString()); sw.Reset(); sw.Start(); // time for int cnt = theList.Count; for (int i = 0; i < cnt; i++) { int inLoop = theList[i]; } Console.WriteLine("list for : " + sw.Elapsed.ToString()); // now run the same tests, but with an array var theArray = theList.ToArray(); sw.Reset(); sw.Start(); foreach (var item in theArray) { int inLoop = item; } Console.WriteLine("array foreach: " + sw.Elapsed.ToString()); sw.Reset(); sw.Start(); // time for cnt = theArray.Length; for (int i = 0; i < cnt; i++) { int inLoop = theArray[i]; } Console.WriteLine("array for : " + sw.Elapsed.ToString()); Console.ReadKey();

Entonces, ejecuté esto en versión con todas las optimizaciones:

list foreach: 00:00:00.5137506 list for : 00:00:00.2417709 array foreach: 00:00:00.1085653 array for : 00:00:00.0954890

Y luego depurar sin optimizaciones:

list foreach: 00:00:01.1289015 list for : 00:00:00.9945345 array foreach: 00:00:00.6405422 array for : 00:00:00.4913245

Por lo tanto, parece bastante consistente, for es más rápido que foreach y las matrices son más rápidas que las listas genéricas.

Sin embargo, esto es a través de 100.000,000 iteraciones y la diferencia es aproximadamente .4 de segundo entre los métodos más rápidos y más lentos. A menos que esté realizando ciclos críticos de rendimiento masivo, no vale la pena preocuparse.