Expresión Lambda - Inferencia del compilador de C #




 Estoy tratando de entender el comportamiento de inferencia del compilador. Por ejemplo, a continuación del fragmento de código, el tipo de tiempo de ejecución del delegado compilado es `Func<int>` 


```
Expression addExpr = Expression.Add(Expression.Constant(2), Expression.Constant(1));
LambdaExpression lambdaExpr1 = Expression.Lambda(addExpr, null);
var compiled = lambdaExpr1.Compile();

```
  Sin embargo debajo de la línea de código no se compila. No estoy seguro de qué es ambiguo aquí para que el compilador lo convierta implícitamente en `Expression<Func<int>>` y asigne una variable al tipo LambdaExpression 


```
LambdaExpression lambdaExp2 = ()=>2+1;

```
  Una posible razón por la que puedo adivinar la expresión lambda en el lado derecho también podría coincidir con la firma de mi delegado personalizado, en cuyo caso el compilador no tiene forma de inferir el tipo de delegado. Pero la misma razón se aplica a mi fragmento de código inicial. Por qué CLR (tiempo de ejecución) puede decidir que puede ser de tipo `Func<int>` . Y si esto es posible y está lo suficientemente cerca como en tiempo de ejecución, ¿por qué no el compilador de c # también puede hacer lo mismo?
Permítanme comenzar replanteando la pregunta de una manera más concisa. 


>  Una expresión lambda se puede convertir a la `Expression<T>` donde `T` es un tipo de delegado compatible con la expresión lambda. `Expression<T>` se deriva de `LambdaExpression` . ¿Por qué entonces no podemos convertir una expresión lambda directamente a `LambdaExpression` ? 
> 
> 

 La razón es: porque esta es una de las situaciones raras en C # donde la información de tipo fluye desde el *tipo de objetivo de asignación* al *tipo de cosa que se asigna* . El compilador debe conocer el tipo de delegado al convertir un lambda; **el compilador de C # no deduce el tipo de delegado de la lambda, sino que verifica que la lambda es compatible con el tipo de delegado dado** . 

 Ahora, ¿podríamos haber diseñado e implementado un sistema en el que si la información de tipo no estuviera presente y el objetivo de conversión fuera `LambdaExpression` , se realizaría una estimación razonable? Por supuesto. No había nada que nos detuviera más que nadie que deseara o necesitara esa característica. 

 Pero la respuesta a la pregunta "¿por qué no existe esta característica?" Siempre es lo mismo. **No estamos obligados a dar una razón para no implementar una función** . Nadie solicitó esa característica, nadie la diseñó, la implementó, probó ni la envió a los clientes. Por lo tanto, ninguna característica. 

 Más bien, las características no existentes requieren que un defensor empiece a convertirlas en características existentes. Si esta es una función que desea o necesita, tómela en el foro de github y defienda la función. O implementarlo usted mismo; El compilador es de código abierto.
bueno, yo no puedo responder por qué no está disponible, pero me puede confirmar que no es un cli problema. el cli de especificaciones no lo menciona (por lo que puedo ver) y si utiliza il directamente, puede crear un atributo genérico. la parte de la c# 3 especificación de que la prohíbe sección 10.1.4 'de la clase base de la especificación de' no dar ningún tipo de justificación. anotado ecma c# 2 spec no da ninguna información útil, aunque no proporciona un ejemplo de lo que no está permitido. mi copia de la annotated c# 3 spec debería de llegar mañana... voy a ver si eso le da más información. de todos modos, es definitivamente un lenguaje de decisión en lugar de en tiempo de ejecución. edit: respuesta de eric lippert (parafraseado): sin ninguna razón en particular, excepto a evitar la complejidad en el lenguaje y compilador para un caso de uso que no agrega mucho valor. En pocas palabras: LINQ to Entities no conoce la conversión de su tipo de ID a una cadena. 

 ¿Cuál es el tipo de `c.ID` ? ¿Hay alguna razón por la que sea un tipo para ID, pero otro para `ReferenzId` ? Si es posible, conviértalos en el mismo tipo, en cuyo punto ya no tendrá más problemas. No sé si hay otras formas de realizar conversiones en LINQ a Entidades (puede haber), pero la alineación de los tipos sería más clara. 

 Por cierto, esto realmente parece que es una combinación: 


```
var query = from c in db.Customers
            join a in db.Addresses on c.Id equals a.ReferenzId into addresses
            select new { Id = c.Id, Addresses = addresses };

```
  EDITAR: Para responder a su comentario: `ToString` aparece en IntelliSense porque el compilador no tiene una idea real de lo que va a significar su consulta ni de cómo se traducirá. Es perfectamente válido C #, y puede generar un árbol de expresiones válido. Es solo que EF no sabe cómo convertir ese árbol de expresiones en SQL. 

 Puede *intentar* usar `Convert.ToString(c.Id)` lugar de simplemente llamar a `c.Id.ToString()` ... Los ejemplos que otros han dado no funcionarán en Entity Framework hoy, porque no se pueden combinar enumeración de clientes y servidores en las entidades LINQ 2. 

 En su lugar, necesita construir una expresión OR, manualmente. 

 Ejecuto una serie de [consejos](http://blogs.msdn.com/alexj/archive/2009/03/26/index-of-tips.aspx) de [EF](http://blogs.msdn.com/alexj/archive/2009/03/26/index-of-tips.aspx) y [este consejo](http://blogs.msdn.com/alexj/archive/2009/03/26/tip-8-writing-where-in-style-queries-using-linq-to-entities.aspx) te muestra cómo construir una expresión OR. 

 Espero que esto ayude 

 Alex eso depende de que versión de tfs que se están ejecutando, así que voy a suponer que es de 2008.en primer lugar, usted debe tener el equipo de edición para que los evaluadores instalado en el equipo que actuará como su agente de compilación, como se indica en cómo: crear una definición de compilaciónhay un par de maneras de decir la formación de equipo para ejecutar las pruebas para su construcción.la unidad de pruebas, se pueden ejecutar una prueba definida la lista dentro de la solución construida. esta lista es la que hace referencia la definición de compilación y todas las pruebas dentro de la lista elegida(s) son ejecutados. más info aquí comodín de la prueba exectution también está disponible mediante la definición de una mascara (es decir, la prueba*.dll) que instruye equipo de construcción para ejecutar alguna de las pruebas presentes en las asambleas que coincida con la máscara. esto se hace cuando la definición de la definición de compilación así. cosas a tener en cuenta:si usted va a utilizar el comodín método y quiero habilitar la cobertura de código para la configuración de prueba, debe agregar lo siguiente a tu archivo de definición para activarlo.$(solutionroot)\testrunconfig.testrunconfig ver a mi pregunta anterior sobre este para más info aquí El autor de este artículo está algo equivocado: en .NET 4.5, la propiedad [AsynchronousProcessing](http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnectionstringbuilder.asynchronousprocessing.aspx) se ignora porque ya no es necesaria. Puede comenzar a [llamar a los métodos Async](http://msdn.microsoft.com/en-us/library/hh211418.aspx) de SqlClient sin cadenas de conexión especiales. 

 Si las operaciones se ejecutarán de forma asíncrona, depende del proveedor de la base de datos. Por ejemplo, la implementación predeterminada de [DbCommand.ExecuteDbDataReaderAsync en](http://msdn.microsoft.com/en-us/library/system.data.common.dbcommand.executedbdatareaderasync.aspx) realidad se ejecuta de forma síncrona y bloquea el hilo de llamada. SqlCommand anula este método y se ejecuta de forma asíncrona. 

 Desafortunadamente, NpgsqlCommand no anula este método, por lo que solo le queda la ejecución síncrona. <p>para comprender lo que hace <code>yield</code>, debe comprender qué <em>generadores</em> son. y antes de que lleguen los generadores <em>iterables</em>.</p><h2>iterables</h2><p>cuando creas una lista, puedes leer sus artículos uno por uno. la lectura de sus elementos uno por uno se llama iteración:</p><pre><code>&gt;&gt;&gt; mylist = [1, 2, 3] &gt;&gt;&gt; for i in mylist: ... print(i) 1 2 3 </code></pre><p><code>mylist</code> es un <em>iterable</em>. cuando usas una comprensión de lista, creas una lista, y por lo tanto una iterable:</p><pre><code>&gt;&gt;&gt; mylist = [x*x for x in range(3)] &gt;&gt;&gt; for i in mylist: ... print(i) 0 1 4 </code></pre><p>todo lo que puede usar &quot;<code>for... in...</code>&quot; en es iterable; <code>lists</code>, <code>strings</code>, archivos ...</p><p>estos iterables son útiles porque puede leerlos tanto como desee, pero almacena todos los valores en la memoria y esto no siempre es lo que desea cuando tiene muchos valores.</p><h2>generadores</h2><p>los generadores son iteradores, una clase de iterable<strong> solo puedes iterar una vez </strong>. los generadores no almacenan todos los valores en la memoria,<strong> generan los valores sobre la marcha </strong>:</p><pre><code>&gt;&gt;&gt; mygenerator = (x*x for x in range(3)) &gt;&gt;&gt; for i in mygenerator: ... print(i) 0 1 4 </code></pre><p>es igual, excepto que usaste <code>()</code> en lugar de <code>[]</code>. pero, usted<strong> no puede </strong>realizar <code>for i in mygenerator</code> por segunda vez, ya que los generadores solo se pueden usar una vez: calculan 0, luego se olvidan y calculan 1, y terminan de calcular 4, uno por uno.</p><h2>rendimiento</h2><p><code>yield</code> es una palabra clave que se usa como <code>return</code>, excepto que la función devolverá un generador.</p><pre><code>&gt;&gt;&gt; def creategenerator(): ... mylist = range(3) ... for i in mylist: ... yield i*i ... &gt;&gt;&gt; mygenerator = creategenerator() # create a generator &gt;&gt;&gt; print(mygenerator) # mygenerator is an object! &lt;generator object creategenerator at 0xb7555c34&gt; &gt;&gt;&gt; for i in mygenerator: ... print(i) 0 1 4 </code></pre><p>este es un ejemplo inútil, pero es útil cuando sabes que tu función devolverá un gran conjunto de valores que solo necesitarás leer una vez.</p><p>para dominar <code>yield</code>, debe comprender que<strong> cuando llama a la función, el código que ha escrito en el cuerpo de la función no se ejecuta. </strong>la función solo devuelve el objeto generador, esto es un poco complicado :-)</p><p>luego, su código continuará desde donde lo dejó cada vez que <code>for</code> usa el generador.</p><p>ahora la parte difícil:</p><p>la primera vez que <code>for</code> llama al objeto generador creado desde su función, ejecutará el código en su función desde el principio hasta que llegue a <code>yield</code>, luego devolverá el primer valor del bucle. luego, cada una de las otras llamadas ejecutará el bucle que ha escrito en la función una vez más y devolverá el siguiente valor, hasta que no haya ningún valor para devolver.</p><p>el generador se considera vacío una vez que se ejecuta la función, pero ya no golpea <code>yield</code>. puede ser porque el bucle llegó a su fin, o porque ya no satisfaces un <code>"if/else"</code>.</p><hr><h2>tu codigo explicado</h2><p>generador:</p><pre><code># here you create the method of the node object that will return the generator def \_get\_child\_candidates(self, distance, min\_dist, max\_dist): # here is the code that will be called each time you use the generator object: # if there is still a child of the node object on its left # and if distance is ok, return the next child if self.\_leftchild and distance - max\_dist &lt; self.\_median: yield self.\_leftchild # if there is still a child of the node object on its right # and if distance is ok, return the next child if self.\_rightchild and distance + max\_dist &gt;= self.\_median: yield self.\_rightchild # if the function arrives here, the generator will be considered empty # there is no more than two values: the left and the right children </code></pre><p>llamador:</p><pre><code># create an empty list and a list with the current object reference result, candidates = list(), [self] # loop on candidates (they contain only one element at the beginning) while candidates: # get the last candidate and remove it from the list node = candidates.pop() # get the distance between obj and the candidate distance = node.\_get\_dist(obj) # if distance is ok, then you can fill the result if distance &lt;= max\_dist and distance &gt;= min\_dist: result.extend(node.\_values) # add the children of the candidate in the candidates list # so the loop will keep running until it will have looked # at all the children of the children of the children, etc. of the candidate candidates.extend(node.\_get\_child\_candidates(distance, min\_dist, max\_dist)) return result </code></pre><p>este código contiene varias partes inteligentes:</p><ul> <li><p>el bucle se repite en una lista, pero la lista se expande mientras se repite el bucle :-) es una forma concisa de revisar todos estos datos anidados, aunque sea un poco peligroso, ya que puede terminar con un bucle infinito. en este caso, <code>candidates.extend(node.\_get\_child\_candidates(distance, min\_dist, max\_dist))</code> agota todos los valores del generador, pero <code>while</code> sigue creando nuevos objetos generadores que producirán valores diferentes de los anteriores ya que no se aplica en el mismo nodo.</p></li> <li><p>el método <code>extend()</code> es un método de objeto de lista que espera un iterable y agrega sus valores a la lista.</p></li> </ul><p>usualmente le pasamos una lista:</p><pre><code>&gt;&gt;&gt; a = [1, 2] &gt;&gt;&gt; b = [3, 4] &gt;&gt;&gt; a.extend(b) &gt;&gt;&gt; print(a) [1, 2, 3, 4] </code></pre><p>pero en tu código recibe un generador, lo cual es bueno porque:</p><ol> <li>no necesitas leer los valores dos veces.</li> <li>es posible que tenga muchos hijos y no quiera que todos se almacenen en la memoria.</li> </ol><p>y funciona porque a python no le importa si el argumento de un método es una lista o no. python espera iterables por lo que trabajará con cadenas, listas, tuplas y generadores. esto se llama tipificación de pato y es una de las razones por las que python es tan genial. pero esta es otra historia, para otra pregunta ...</p><p>puede detenerse aquí, o leer un poco para ver un uso avanzado de un generador:</p><h2>controlando el agotamiento de un generador.</h2><pre><code>&gt;&gt;&gt; class bank(): # let's create a bank, building atms ... crisis = false ... def create\_atm(self): ... while not self.crisis: ... yield "$100" &gt;&gt;&gt; hsbc = bank() # when everything's ok the atm gives you as much as you want &gt;&gt;&gt; corner\_street\_atm = hsbc.create\_atm() &gt;&gt;&gt; print(corner\_street\_atm.next()) $100 &gt;&gt;&gt; print(corner\_street\_atm.next()) $100 &gt;&gt;&gt; print([corner\_street\_atm.next() for cash in range(5)]) ['$100', '$100', '$100', '$100', '$100'] &gt;&gt;&gt; hsbc.crisis = true # crisis is coming, no more money! &gt;&gt;&gt; print(corner\_street\_atm.next()) &lt;type 'exceptions.stopiteration'&gt; &gt;&gt;&gt; wall\_street\_atm = hsbc.create\_atm() # it's even true for new atms &gt;&gt;&gt; print(wall\_street\_atm.next()) &lt;type 'exceptions.stopiteration'&gt; &gt;&gt;&gt; hsbc.crisis = false # the trouble is, even post-crisis the atm remains empty &gt;&gt;&gt; print(corner\_street\_atm.next()) &lt;type 'exceptions.stopiteration'&gt; &gt;&gt;&gt; brand\_new\_atm = hsbc.create\_atm() # build a new one to get back in business &gt;&gt;&gt; for cash in brand\_new\_atm: ... print cash $100 $100 $100 $100 $100 $100 $100 $100 $100 ... </code></pre><p><strong> nota: </strong>para python 3, use<code>print(corner\_street\_atm.\_\_next\_\_())</code> o <code>print(next(corner\_street\_atm))</code></p><p>puede ser útil para varias cosas como controlar el acceso a un recurso.</p><h2>itertools, tu mejor amigo.</h2><p>el módulo de itertools contiene funciones especiales para manipular iterables. ¿alguna vez desea duplicar un generador? ¿encadenar dos generadores? ¿agrupar valores en una lista anidada con una sola línea? <code>map / zip</code> sin crear otra lista?</p><p>entonces solo <code>import itertools</code>.</p><p>¿un ejemplo? veamos las posibles órdenes de llegada para una carrera de cuatro caballos:</p><pre><code>&gt;&gt;&gt; horses = [1, 2, 3, 4] &gt;&gt;&gt; races = itertools.permutations(horses) &gt;&gt;&gt; print(races) &lt;itertools.permutations object at 0xb754f1dc&gt; &gt;&gt;&gt; print(list(itertools.permutations(horses))) [(1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2), (2, 1, 3, 4), (2, 1, 4, 3), (2, 3, 1, 4), (2, 3, 4, 1), (2, 4, 1, 3), (2, 4, 3, 1), (3, 1, 2, 4), (3, 1, 4, 2), (3, 2, 1, 4), (3, 2, 4, 1), (3, 4, 1, 2), (3, 4, 2, 1), (4, 1, 2, 3), (4, 1, 3, 2), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 2, 1)] </code></pre><h2>entendiendo los mecanismos internos de iteración.</h2><p>la iteración es un proceso que implica iterables (implementación del método <code>\_\_iter\_\_()</code>) e iteradores (implementación del método <code>\_\_next\_\_()</code>). iterables son cualquier objeto de los que puede obtener un iterador. los iteradores son objetos que le permiten iterar en iterables.</p><p>hay más información al respecto en este artículo sobre <a href="http://effbot.org/zone/python-for-statement.htm">cómo funcionan <code>for</code> loops</a> .</p> Como te va, te recomendaría que hagas la consulta de la siguiente manera para ver si es lo que estas necesitando:  
select campo1, campo2, campo3  
from tabla  
where campo1 like ('%expresion%') and campo1 like ('%expresion1%')   
Si esto no te resulta, dime que intentamos algún camino alternativo,  
Sin más,  
Leandro amigo revisa otros filtros, principalmente los de los 24 volt hacia el inversor, si todo ok, puede ser por protecci&oacute;n del conversor dc-dc que est&aacute; notando alg&uacute;n agotamiento en las l&aacute;mparas, de ser as&iacute; tendr&aacute;s que cambiarlas o desactivar la protecci&oacute;n desde el mismo integrado, si no sabes c&oacute;mo enviar su n&uacute;mero para que alg&uacute;n colega te explique q hacer, ya que en todos no es igual, pero si efectivo, revisa y comenta resultados. saludos y suerte true.                          
--
mira si quisiste poner x en lugar de 0, entonces es el intervalo tal que x es menor o igual a 2, por lo tanto un intervalo del -∞ a 2, cerrado por la derecha (por que se incluye al dos).

(-∞ ; 2]    --> representación formal.


si quisiste decir todos los valores que están entre 0 y 2, debería ser expresado de otra manera, como esta: 0<= x <=2 o 0< x <=2, y dependiendo de como lo expreses (mayor o igual, o mayor que cero) va a ser la representación del intervalo.

[0; 2] --> mayor igual.

(0; 2] --> mayor. *Cattelan Piel En Italia Comedor 2019Lindos Sofá De Silla Magda rdoeCBx*Me da la impresión de que iterparse es lo que quieres. Mirando
la sección "Eventos de etiqueta selectiva" en [http://lxml.de/parsing.html](/parsing.html) parece que
eso te da lo que deseas:



```
context = etree.iterparse(xmlfile, tag="yourSubTree")
action, elem = context.next()
etree.iterwalk(elem, ...)...

```

Parece que XPath también podría funcionar, pero supongo que
XPath lee en todo el árbol antes de regresar, mientras que yo
esperaría que iterparse caminara solo hasta que tuviera una
coincidencia. Valdría la pena perfilar los dos enfoques.