Lambda表达式编译

6 c# compiler-construction lambda byte equality

给定下面的lambda表达式,其中省类型包含公共属性"byte CountryId"和包含公共属性"byte Id"的Country类型.

Expression<Func<Province, bool>> exp = p => p.CountryId == country.Id;
Run Code Online (Sandbox Code Playgroud)

该表达式稍后由NHibernate Linq提供程序使用并引发异常.当我检查表达式变量exp时,我发现相等运算符的两边都转换为Int32.

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

我无法理解为什么两个字节值的相等运算符需要事先将这些值转换为Int32.我已经直接编写了表达式,并且让编译器为我做了.以下表达式由NHibernate Linq提供者转换得很好.

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
      );
Run Code Online (Sandbox Code Playgroud)

因此,编译器必须输出具有类型转换的表达式.有任何想法吗?

jas*_*son 6

这符合规范.引自§4.1.5:

C#支持九种整数类型:sbyte,byte,short,ushort,int,uint,long,ulong,和char.[...]

积分型一元和二元运算符始终以带符号的32位精度,无符号32位精度,带符号的64位精度或无符号64位精度运行:

[...]

对于二元+,,*,/,%,&,^,|,==,!=,>,<,>=,和<=运营商,操作数被转换为类型T,其中T是int,UINT,长和ulong一个可以完全表示两者的所有可能值的操作数.然后使用类型T的精度执行操作,结果的类型是T(或关系运算符的bool).不允许一个操作数为long类型,另一个操作数为binary类型的二元运算符.

因此,为

byte b1;
byte b2;
bool b = (b1 == b2);
Run Code Online (Sandbox Code Playgroud)

调用操作数b1b2int之前被提升==.

  • 谢谢你的回答.这解释了将字节类型值转换为int32的编译器行为.但是,它仍然没有意义.由于lambda表达式被转换为表达式而不是已编译的委托,因此它必须仍然是一个表达式树,以后可以用任何语言定义,包括C#,HQL等.所以我认为它必须没有任何特定于语言的实现.NHibernate Linq提供程序在对它们进行操作之前不需要提升变量类型.lambda表达式在转换为表达式树之前是否已编译? (5认同)