variable usa tipo referencia por pero pasar parametros objetos metodos locales las inicializar implícito deben con como clases anonimos c# linq-to-sql lambda anonymous-methods

usa - pasar objetos como parametros en c#



C#: ¿Es posible declarar una variable local en un método anónimo? (6)

El método Where toma un Func así que lo que está pasando allí en la segunda parte no es en realidad un método, sino solo una expresión bool. Mi sugerencia sería tener un método real que devuelva un bool, que tome los parámetros que necesita, y en su llamada al método Where simplemente haga algo como esto Where (p => MyMethod (p, ...))

Es posible tener una variable local en un método c # anónimo, es decir, en el siguiente código me gustaría realizar el recuento solo una vez.

IQueryable<Enquiry> linq = db.Enquiries; if(...) linq = linq.Where(...); if(...) linq = linq.Where(e => (x <= (from p in db.Orders where p.EnquiryId == e.Id select p).Count() && (from p in db.Orders where p.EnquiryId == e.Id select p).Count() <= y)); if(...) linq = linq.Where(...); var result = (from e in linq select e);

¿Hay un "let" para las funciones anónimas?

Actualización: Tenga en cuenta que estoy agregando varias cláusulas Where después de esta declaración, por lo que no puedo cerrar con una selección.

/ Niels


Si está utilizando Linq para SQL, no podrá usar la respuesta de Mehrdad Afshari. Sus expresiones LINQ deben ser Árboles de expresión, y no admiten la sintaxis de delegado anónimo.

Tampoco podrá crear su delegado en otro lugar y llamarlo desde el interior del lambda. Linq to SQL solo permite que se realicen ciertas operaciones en el cuerpo de la consulta, y llamar a un delegado no es una de ellas.

Su mejor apuesta, suponiendo que esté utilizando Linq a SQL (como aparece dado su ejemplo), es reducir el recuento en una consulta, luego capturar la variable de conteo en la consulta que requiere el recuento.


Con un poco de experiencia en Scheme, sabría que ''let'' es solo azúcar de sintaxis para definir una lambda e invocarla.

Entonces con ese conocimiento, veamos cómo se puede hacer.

(count => x <= count && count <= y) ((from p in db.Orders where p.EnquiryId == e.Id select p).Count())

Como beneficio adicional, parece que Scheme también :)

Descargo de responsabilidad: no probé este fragmento, pero no hay ninguna razón por la que no debería funcionar. Personalmente, usaría la construcción ''let'' proporcionada en LINQ.

Actualizar:

No funciona... :(


Sí, puedes hacer exactamente lo que quieras, en Linq para objetos y Linq para SQL.

Hay un permiso en Linq, que le permite dar un nombre a un resultado intermedio en el medio de su consulta, tal como lo desea. Basado en tu ejemplo:

... = from e in linq let count = (from p in db.Orders where p.EnquiryId == e.Id select p).Count() where (x <= count) && (count <= y) select e;

Por cierto, creo que hay algo sintácticamente erróneo sobre tu ejemplo original, que es más fácil de detectar cuando el count es solo un nombre:

where (x <= count) && /* <= */ (count <= y);


¡¿Si por qué no?! ¡Después de todo, es una función, solo anónimo!

Ejemplo:

x => { int y = x + 1; return x + y; }

O alternativamente:

delegate(int x) { int y = x + 1; return x + y; }

Entonces tu código puede escribirse como:

... = linq.Where(e => { var count = (from p in db.Orders where p.EnquiryId == e.Id select p).Count(); return x <= count && count <= y; });

ACTUALIZACIÓN: para aclarar las cosas sobre el comentario, es importante saber la diferencia entre los métodos anónimos y las expresiones lambda. Un método anónimo es como un método normal, sin un nombre explícito. Cuando lo compila, el compilador genera un método normal con un nombre extraño para usted, por lo que no tendrá ninguna limitación especial. Sin embargo, una representación de un método anónimo es una expresión lambda. Las expresiones Lambda se pueden interpretar de dos maneras diferentes. El primero es un delegado. De esa manera, son iguales a un método anónimo. El segundo es un árbol de expresiones. De esta manera, LINQ to SQL lo utiliza normalmente y algunos otros proveedores de LINQ. No ejecutan su expresión directamente de ninguna manera. Lo analizan como un árbol de expresiones y usan el árbol como datos de entrada para generar la declaración SQL equivalente que se ejecutará en el servidor. No se ejecuta como un método y no se considera un método anónimo. En ese caso, no puede definir una variable local ya que no es posible analizar el lambda como un árbol de expresiones.


Me encontré con un problema similar. La solución es crear un método de generación de árbol de expresiones personalizado.

Hice mi pregunta en MSDN-foros. Por favor, consulte la pregunta y la respuesta aquí: Reutilizando expresiones de Where .

Esto puede darte una idea de cómo proceder, pero debo admitir que los árboles de expresiones personalizadas no son para los pusilánimes ;-)