2010-02-09 22 views
13

Duplicar posible:
C# foreach vs functional eachforeach (... en ...) o .ForEach(); esa es la cuestión

Ésta es una pregunta acerca de la codificación para facilitar la lectura.

Tengo un XDocument y un de los nombres de los elementos que contienen información confidencial que necesito enmascarar (reemplazar con guiones bajos en este ejemplo).

XDocument xDoc; 
List<string> propertiesToMask; 

Esto se puede escribir de dos maneras, usando foreach lazos tradicionales, o el uso de métodos .ForEach con la sintaxis Lamba.

foreach (string propertyToMask in propertiesToMask) 
{ 
    foreach (XElement element in xDoc.Descendants(propertyToMask)) 
    { 
     element.SetValue(new string('_', element.Value.Length)); 
    } 
} 

o

propertiesToMask 
    .ForEach(propertyToMask => xDoc.Descendants(propertyToMask).ToList() 
     .ForEach(element => element.SetValue(new string('_', element.Value.Length)))); 

¿Qué enfoque crees que es el más fácil de leer, y por qué? Si prefiere el segundo ejemplo, ¿cómo lo presentaría para una máxima legibilidad?

Respuesta

14
foreach (string propertyToMask in propertiesToMask) 
{ 
    foreach (XElement element in xDoc.Descendants(propertyToMask)) 
    { 
     element.SetValue(new string('_', element.Value.Length)); 
    } 
} 

Porque el espaciado hace que sea muy fácil de escanear. El segundo está muy desordenado y tengo que leerlo.

+1

El segundo me parece bien. Mucho menos revuelto. –

+0

Y por las razones sugeridas en la publicación de Mehrdad. –

+2

El código legible puede ser tan importante como el código eficiente (siempre y cuando no sea un código malicioso) – Jrud

14

Eric Lippert tiene un good entry about this on his blog. En resumen, la misma tarea realizada por ForEach es producir efectos secundarios que pueden no ser deseables con el estilo funcional de programación en C#.

+0

+1. Este artículo fue exactamente lo que me vino a la mente cuando leí la publicación. ¡Y tu resumen es excelente! – TrueWill

4

Yo prefiero la primera, por tres razones.

En primer lugar, es más eficiente (en el segundo, tiene llamadas ToList() adicionales).

En segundo lugar, es más legible, en mi opinión.

Por último, recomendaría leer Eric Lippert's blog post on this subject. Hay razones filosóficas para evitar , ya que su propósito es causar efectos secundarios, a pesar de que tiene un estilo funcional.

0

Aquí es una respuesta muy subjetiva:

yo no estoy muy de acuerdo con el razonamiento filosófico detrás no le gustaba .ForEach. Tal vez es mi falta de experiencia en ciencias de la computación, no lo sé.

Para mí, el segundo conjunto de códigos es más fácil de leer y parece mucho menos confuso. Como otros han mencionado, ToList() es desafortunado, pero aún así me parece mejor.

Me gusta la solución de Daniel Brückner aún mejor. Parece mejor que cualquiera de las otras soluciones propuestas.

1

El primero se puede modificar mientras se está ejecutando el depurador y Visual Studio le permite continuar con la depuración. Después de modificar la variante .ForEach, debe reiniciar la sesión de depuración y volver a compilar, ya que contiene una expresión lambda (VS 2008)

4

La forma tradicional tiene la gran ventaja de que se puede depurar fácilmente.Pero yo personalmente preferiría el enfoque ForEach() en este caso. La circunstancia de que es difícil depurar el código escrito de forma fluida es, en mi opinión, un defecto de las herramientas disponibles, no del estilo de codificación. En mi experiencia personal, la tasa de error en tales métodos es muy baja, por lo que no es realmente un gran problema.

Escribo algunos métodos de extensión que producen el siguiente código.

propertiesToMask 
    .SelectMany(property => document.Descendants(property)) 
    .ForEach(element => element.MaskValue()); 
+0

Me gusta mucho este código. –

+0

También me gustan las interfaces fluidas, pero este ejemplo tiene efectos secundarios. Por favor, vea las publicaciones de @Mehrdad y @Reed. – TrueWill

+0

(Casi) Todas las interfaces fluidas causan efectos secundarios. Leí la publicación de Eric antes y entiendo su punto de no presentar ForEach() junto con todos los métodos LINQ libres de efectos secundarios. Pero no creo que el método sea malo per se. Tiene efectos secundarios. Muchos métodos lo hacen. Si está acostumbrado a este estilo, no hay peligro de perder los efectos secundarios. El gran punto para mí es la legibilidad ... ¿puedes hacerlo (mucho) mejor? Incluso con una sintaxis (hipotética) distinta de C#, esto parece estar cerca del óptimo para mí. –