2010-01-15 14 views
6

Dada la expresión lambda a continuación donde el tipo de provincia contiene una propiedad pública "byte CountryId" y un tipo de país que contiene una propiedad pública "Id de byte".Compilación de expresiones Lambda

Expression<Func<Province, bool>> exp = p => p.CountryId == country.Id; 

La expresión es utilizada posteriormente por el proveedor NHibernate Linq y lanzó una excepción. Cuando inspeccioné la variable de expresión exp, descubrí que ambos lados del operador de igualdad se convirtieron a Int32.

{p => (Convert(p.CountryId) = Convert(value 
(AddressToGo.Business.Default.AddressComponents+<>c__DisplayClass0).country.Id))} 

no puedo entender por qué el operador de igualdad para los dos valores de byte necesita esos valores que ser convertido a Int32 antemano. Escribí la expresión directamente sin dejar que el compilador lo haga por mí. La siguiente expresión es convertida por el proveedor NHibernate Linq muy bien.

ParameterExpression prm = Expression.Parameter(typeof(Province), "p"); 
    Expression<Func<Province, bool>> exp = 
     Expression.Lambda<Func<Province, bool>> 
     (
     Expression.Equal 
     (
      Expression.MakeMemberAccess(prm, typeof(Province).GetProperty("CountryId")), 
      Expression.Constant(country.Id, typeof(byte)) 
     ), 
     prm 
    ); 

Por lo tanto, debe haber una razón por la cual el compilador emite la expresión con conversión de tipo. ¿Algunas ideas?

+0

Necesita una etiqueta de idioma. –

Respuesta

6

Esto es según las especificaciones. Citando §4.1.5:

C# soporta nueve tipos integrales: sbyte, byte, short, ushort, int, uint, long, ulong y char. [...]

El de tipo integral operadores unarios y binarios siempre operan con una precisión de 32 bits con signo, sin signo de 32 bits de precisión, firmado precisión de 64 bits, con o sin signo de 64 bits de precisión:

[ ...]

Para el binario +, , *, /, %, &, ^, |, ==, !=, >, <, >= y <= operadores, los operandos se convierten a tipo T, donde T es el primero de int, uint, long y ulong que puede representar por completo todos los valores posibles de los dos operandos. La operación se realiza usando la precisión de tipo T, y el tipo de resultado es T (o bool para los operadores relacionales). No está permitido que un operando sea de tipo largo y el otro sea de tipo ulong con los operadores binarios.

Así, por

byte b1; 
byte b2; 
bool b = (b1 == b2); 

los operandos b1 y b2 son promovidos a int antes == se invoca.

+5

Gracias por la respuesta. Esto explica el comportamiento del compilador al convertir los valores de tipo de byte a int32. Sin embargo, todavía no tiene sentido. Como la expresión lambda se convierte en una expresión, no en un delegado compilado, debe seguir siendo un árbol de expresiones que luego se puede definir en cualquier idioma, incluidos C#, HQL, etc. Por lo tanto, creo que debe estar libre de implementaciones específicas del idioma.El proveedor NHibernate Linq no necesitaría la promoción de tipos variables antes de operar en ellos. ¿La expresión lambda se compila antes de convertirse a un árbol de expresiones? –