variable usa tipo pero locales las inicializar implícito expresiones deben con como c# linq

c# - usa - Construir una consulta LINQ mediante programación sin que las variables locales me engañen



expresiones lambda c# where (3)

Supongamos que mis objetos están en perfecto estado de funcionamiento (es decir, TDD me hace pensar que funcionan).

Tengo una lista que creo así (excepto sangrado adecuadamente):

var result = from v in vendors from p in v.Products orderby p.Name select p;

Esto funciona: recibo todos los productos de todos los proveedores.

Ahora tengo una lista de condiciones, desarrolladas en tiempo de ejecución por el usuario. Vamos a aplicarlos:

foreach (Attribute a in requiredAttributes) { result = result.Where(p => p.Attributes.Contains(a)); }

Esto puede ser primitivo, pero pensé que funcionaría. Sin embargo, después de que este bucle foreach haya finalizado, cuando enumere el "resultado" contendrá todos los productos que tengan el ÚLTIMO atributo de la colección de atributos necesarios en su propiedad Atributos (también una colección).

Para mí, esto huele a "a" se sobrescribe en algún lugar con cada viaje a través del ciclo, y solo se aplica el último.

Aparte de escribir de alguna manera un método de extensión a IEnumerable llamado ContainsAll (IEnumerable) o algo por el estilo, ¿cómo puedo lograr lo que quiero, que es básicamente un Y lógico, dándome solo aquellos productos que tienen TODOS los atributos requeridos?


(Editado para mayor claridad)

El problema es el ciclo foreach, y el hecho de que la variable "a" está siendo capturada y luego cambiada cada vez. Aquí hay una modificación que funcionará, al introducir efectivamente una variable "nueva" para cada iteración del ciclo y capturar esa nueva variable.

foreach (Attribute a in requiredAttributes) { Attribute copy = a; result = result.Where(p => p.Attributes.Contains(copy)); }

La solución de Omer es más limpia si puede usarla, pero esto puede ayudar si su código real es realmente más complicado :)

EDITAR: Hay más sobre el tema en este artículo sobre cierres : desplácese hacia abajo para "Comparar estrategias de captura: complejidad versus potencia".


No lo he codificado, pero cambio

foreach (Attribute a in requiredAttributes){ result = result.Where(p => p.Attributes.Contains(a)); }

a

foreach (Attribute a in requiredAttributes){ Attribute b = a; result = result.Where(p => p.Attributes.Contains(b)); }

debería arreglarlo también, creo.


var result = from v in vendors from p in v.Products where requiredAttributes.All(a => p.Attributes.Contains(a)) orderby p.Name select p;

HTH.