2010-01-15 5 views
6

Data l'espressione lambda in basso in cui il tipo Provincia contiene una proprietà pubblica "byte ID Paese" e il tipo Paese che contiene una proprietà pubblica "ID byte".Compilazione espressione lambda

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

Expression viene in seguito utilizzato dal provider Linq di NHibernate e ha generato un'eccezione. Quando ho controllato l'espressione variable exp, ho scoperto che entrambi i lati dell'operatore di uguaglianza sono stati convertiti in Int32.

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

non riesco a capire il motivo per cui l'operatore di uguaglianza per due valori di byte ha bisogno di quei valori per essere convertito in Int32 anticipo. Ho scritto l'espressione direttamente senza lasciare che sia il compilatore a farlo per me. La seguente espressione viene convertita dal provider di Linq di NHibernate.

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 
    ); 

Quindi, ci deve essere un motivo per cui il compilatore emette l'espressione di conversione di tipo. Qualche idea?

+0

Richiede un tag di lingua. –

risposta

6

Questo è conforme alle specifiche. Citando §4.1.5:

C# supporta nove tipi integrali: sbyte, byte, short, ushort, int, uint, long, ulong e char. [...]

L'integrale di tipo operatori unari e binari funzionano sempre con precisione firmato 32 bit, 32 bit senza segno precisione, con segno a 64 bit di precisione, con o senza segno a 64 bit di precisione:

[ ...]

Per il binario +, , *, /, %, &, ^, |, ==, !=, >, <, Gli operatori >= e <=, gli operandi vengono convertiti in tipo T, dove T è il primo di int, uint, long e ulong che può rappresentare tutti i valori possibili di entrambi gli operandi. L'operazione viene quindi eseguita utilizzando la precisione di tipo T e il tipo del risultato è T (o bool per gli operatori relazionali). Non è consentito che un operando sia di tipo lungo e l'altro sia di tipo più lungo con gli operatori binari.

Così, per

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

operandi b1 e b2 sono promossi a int prima == viene richiamato.

+5

Grazie per la risposta. Questo spiega il comportamento del compilatore di convertire i valori del tipo di byte in int32. Tuttavia, non ha ancora senso. Poiché l'espressione lambda viene convertita in un'espressione, non in un delegato compilato, deve comunque essere un albero di espressioni che può essere successivamente definito in qualsiasi linguaggio, inclusi C#, HQL, ecc. Quindi penso che sia privo di implementazioni specifiche della lingua.Il provider di NHibernate Linq non avrebbe bisogno della promozione di tipi di variabili prima di operare su di essi. L'espressione lambda viene compilata prima di essere convertita in un albero di espressione? –