给定下面的lambda表达式,其中省类型包含公共属性“byte CountryId”和包含公共属性“byte Id”的Country类型。
Expression<Func<Province, bool>> exp = p => p.CountryId == country.Id;
该表达式稍后由NHibernate Linq提供程序使用并引发异常。当我检查表达式变量exp时,我发现相等运算符的两边都转换为Int32。
{p => (Convert(p.CountryId) = Convert(value
(AddressToGo.Business.Default.AddressComponents+<>c__DisplayClass0).country.Id))}
我无法理解为什么两个字节值的相等运算符需要事先将这些值转换为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
);
因此,编译器必须输出具有类型转换的表达式。有什么想法吗?
答案 0 :(得分:6)
这是符合规范的。引自§4.1.5:
C#支持九种完整类型:
sbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
和char
。 [...]积分型一元和二元运算符始终使用带符号的32位精度,无符号32位精度,带符号的64位精度或无符号64位精度运行:
[...]
对于二进制
+
,–
,*
,/
,%
,&
,^
,{{ 1}},|
,==
,!=
,>
,<
和>=
运营商,< strong>操作数转换为类型T,其中T是int,uint,long和ulong中的第一个,它们可以完全表示两个操作数的所有可能值。然后使用类型T的精度执行操作,结果的类型是T(或关系运算符的bool)。不允许一个操作数的类型为long,另一个操作数的类型为ulong,使用二元运算符。
因此,对于
<=
在调用byte b1;
byte b2;
bool b = (b1 == b2);
之前,操作数b1
和b2
会提升为int
。