Компиляция лямбда-выражений - PullRequest
6 голосов
/ 15 января 2010

Учитывая лямбда-выражение ниже, где тип Провинции содержит открытое свойство "byte CountryId" и тип страны, который содержит публичное свойство "byte Id"

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

Итак, должна быть причина, по которой компилятор выводит выражение с преобразованием типов. Есть идеи?

1 Ответ

6 голосов
/ 15 января 2010

Это согласно спецификации. Цитата из п. 4.1.5:

C # поддерживает девять целых типов: sbyte, byte, short, ushort, int, uint, long, ulong и char. [...]

Унарные и двоичные операторы целочисленного типа всегда работают с 32-разрядной точностью со знаком, 32-разрядной точностью без знака, 64-разрядной точностью со знаком или 64-разрядной точностью без знака:

[...]

Для двоичного файла +, , *, /, %, &, ^, |, ==, !=, >, <, >= и <= операторы, операнды преобразуются в тип T, где T является первым из int, uint, long и ulong, которые могут полностью представлять все возможные значения обоих операндов . Затем операция выполняется с использованием точности типа T, а тип результата - T (или bool для реляционных операторов). Не допускается, чтобы один операнд имел тип long, а другой - тип ulong с бинарными операторами.

Таким образом, для

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

операнды b1 и b2 повышаются до int до вызова ==.

...