2011-10-20 14 views
10

¿Hay alguna forma mejor de realizar estas asignaciones con LINQ?¿Hay alguna forma de establecer valores en LINQ?

IEnumerable<SideBarUnit> sulist1 = newlist.Where(c => c.StatusID == EmergencyCV.ID); 
foreach (SideBarUnit su in sulist1) su.color = "Red"; 
+1

posible duplicado de [equivalente LINQ de foreach para IEnumerable ] (http://stackoverflow.com/questions/200574/linq-equivalent-of-foreach-for-ienumerablet) –

Respuesta

8

Usted puede hacer tal cosa, ya que las otras respuestas aquí señalan, pero luego que ya no están utilizando LINQ.

Eric Lippert escribió an excellent blog post about this very subject, que le recomiendo que lea.He aquí un extracto:

estoy filosóficamente opone a facilitar un procedimiento de este tipo, por dos razones.

La primera razón es que hacerlo viola los principios de programación funcional en los que se basan todos los demás operadores de secuencia. Claramente el único propósito de una llamada a este método es causar efectos secundarios.

El propósito de una expresión es calcular un valor, no para causar un efecto secundario.

...

La segunda razón es que al hacerlo agrega un nuevo poder de representación cero a la lengua. Hacer esto le permite reescribir el código perfectamente claro:

foreach(Foo foo in foos){ statement involving foo; } 

en este código:

foos.ForEach((Foo foo)=>{ statement involving foo; }); 

que utiliza casi exactamente los mismos caracteres en orden ligeramente diferente. Y, sin embargo, la segunda versión es más difícil de entender, más difícil de depurar e introduce la semántica de cierre, con lo que potencialmente se modifican los tiempos de vida de los objetos de manera sutil.

+2

+1 Otros lo han mencionado, y otros han seguido y han mostrado ejemplos de ForEach(). No podría estar más de acuerdo con Eric Lippert aquí. Quizás publicando este extracto explícitamente convencerá al OP, o tal vez no. Aún así, la mejor respuesta IMO. – Didaxis

4

La forma más sencilla es definir un método foreach de extensión que le permite añadir sobre el extremo de una consulta de este tipo. Por ejemplo

public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action) { 
    foreach (var cur in enumerable) { 
    action(cur); 
    } 
} 

... 

uso:

newlist 
    .Where(c => c.StatusID == EmergencyCV.ID) 
    .ForEach(cur => cur.color = "Red"); 
4

Usando List.ForEach() método:

IEnumerable<SideBarUnit> sulist1 = 
    newlist.Where(c => c.StatusID == EmergencyCV.ID) 
      .ToList() 
      .ForEach(item => item.color = "Red"); 

PS: Yo sé de article Eric Lippert aboout ForEach() vs foreach, pero de todos modos es útil y yo prefiero que esté más bien que for/foreach bucles

EDIT: relación con la pregunta en el comentario sobre el rendimiento golpea

Enumerable.ToList() implementan como

public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source) 
{ 
    if (source == null) 
    { 
     throw Error.ArgumentNull("source"); 
    } 
    return new List<TSource>(source); 
} 

impacto en el rendimiento por lo que es un tiempo para crear una nueva instancia List<>().

MSDN dice a continuación para List<>(IEnumerable<>) ctor:

Inicializa una nueva instancia de la clase de lista que contiene elementos copiados de la colección especificada y tiene capacidad suficiente para acomodar el número de elementos copiados.

por lo que no sería una operación de copia de toda la lista de

+1

En otras palabras, la colección es en bucle dos veces – Magnus

+1

'ForEach' no es una" característica "exclusiva de Linq. De hecho, no tiene relación alguna con Linq. Por lo tanto, supongo que su respuesta, en realidad, es "no, pero aquí hay una alternativa". Los consejos sobre _ [por qué] (http://stackoverflow.com/questions/7838458/is-there-a-way-to-set-values-in-linq/7838525#7838525) _ serían una gran pieza de entrada a esta respuesta, en lugar de que el OP salga con una falsa impresión de que se trata de Linq. –

+0

@Mr. Decepción: absolutamente, LINQ termina después de la llamada 'ToLisT()' – sll

4

LINQ es todo acerca de la selección, no actualizar. pero se puede usar ToList y ParaCada de la Lista de actualizar los elementos:

newlist.Where(c => c.StatusID == EmergencyCV.ID). 
    ToList(). 
    ForEach(su => su.color = "Red"); 

No estoy seguro de la legibilidad es mejor, aunque ...

+0

@vs 74 ¿Hay un golpe de rendimiento al convertir de IEnum <> a una Lista <>? – 0x4f3759df

+2

@iterationx, así se creará una nueva lista, por lo que no es tan eficiente como iterar + Creo que es menos legible, así que no estoy seguro de que valga la pena utilizar esta técnica ... –

2

LINQs propósito es principalmente para consultar/proyecto/transformar los datos.

Es posible que desee utilizar el método de extensión ForEach. Pero vea this discussion para más detalles.

1

Se podría utilizar un método anónimo en una instrucción Select:

var sulist1 = newlist.Where(c => c.StatusID == EmergencyCV.ID) 
        .Select(c => { 
            c.color = "Red"; 
            return c; 
            }); 
+0

En realidad, no creo que esto funcione a menos que la nueva lista se itere – Davy8

Cuestiones relacionadas