2010-01-15 58 views
6

Với biểu thức lambda bên dưới, loại tỉnh chứa thuộc tính công khai "byte CountryId" và loại Quốc gia có chứa thuộc tính công khai "Id byte".Biên dịch biểu thức Lambda

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

Biểu thức sau này được nhà cung cấp NHibernate Linq sử dụng và đã ném ngoại lệ. Khi tôi kiểm tra exp biến biểu thức, tôi phát hiện ra rằng cả hai mặt của toán tử bình đẳng đã được chuyển thành Int32.

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

Tôi không hiểu tại sao toán tử bình đẳng cho hai giá trị byte cần các giá trị đó được chuyển đổi thành Int32 trước. Tôi đã viết các biểu thức trực tiếp wihout cho phép trình biên dịch làm điều đó cho tôi. Biểu thức sau được chuyển đổi bởi nhà cung cấp NHibernate Linq tốt.

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

Vì vậy, phải có lý do khiến trình biên dịch đưa ra biểu thức với chuyển đổi loại. Bất kỳ ý tưởng?

+0

Cần thẻ ngôn ngữ. –

Trả lời

6

Đây là thông số kỹ thuật. Trích dẫn từ §4.1.5:

C# hỗ trợ chín loại không thể thiếu: sbyte, byte, short, ushort, int, uint, long, ulong, và char. [...]

Các thể thiếu loại nhà khai thác unary và nhị phân luôn hoạt động với ký 32-bit chính xác, không dấu 32-bit chính xác, có chữ ký chính xác 64-bit hoặc 64-bit không chính xác:

[ ...]

Đối với nhị phân +, , *, /, %, &, ^, |, ==, !=, >, <, Các toán tử >=<=, các toán hạng được chuyển thành loại T, trong đó T là đầu tiên của int, uint, long và ulong có thể đại diện cho tất cả các giá trị có thể của cả hai toán hạng. Thao tác này sau đó được thực hiện bằng cách sử dụng độ chính xác của loại T, và loại kết quả là T (hoặc bool cho các toán tử quan hệ). Nó không được phép cho một toán hạng được loại dài và khác là loại ulong với các toán tử nhị phân.

Như vậy, đối với

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

các toán hạng b1b2 được thăng int trước == được gọi.

+5

Cảm ơn bạn đã trả lời. Điều này giải thích hành vi của trình biên dịch chuyển đổi các giá trị kiểu byte thành int32. Tuy nhiên, nó vẫn không có ý nghĩa. Vì biểu thức lambda được chuyển đổi thành một biểu thức, không phải là một ủy nhiệm được biên dịch, nó vẫn phải là một cây biểu thức mà sau này có thể được định nghĩa bằng bất kỳ ngôn ngữ nào, bao gồm C#, HQL vv. Vì vậy, tôi nghĩ rằng nó phải không có bất kỳ ngôn ngữ cụ thể nào.Nhà cung cấp LINiber NHibernate sẽ không cần quảng bá các loại biến trước khi hoạt động trên chúng. Là biểu thức lambda biên dịch trước khi được chuyển đổi thành một cây biểu thức? –

Các vấn đề liên quan