2011-10-14 70 views
43

Tôi tự hỏi chính xác sự khác nhau giữa gói một đại biểu bên trong Expression<> và không?Mục đích của lớp Expression là gì?

Tôi thấy Expression<Foo> đang được sử dụng rất nhiều với LINQ, nhưng cho đến giờ tôi chưa tìm thấy bất kỳ bài viết nào giải thích sự khác biệt giữa điều này và chỉ sử dụng một đại biểu.

Ví dụ:

Func<int, bool> Is42 = (value) => value == 42; 

vs

Expression<Func<int, bool>> Is42 = (value) => value == 42; 

Trả lời

48

Bằng cách lưu trữ một lambda như một đại biểu, bạn đang lưu trữ một trường hợp cụ thể của một đại biểu thực hiện một số hành động. Nó không thể được sửa đổi, bạn chỉ cần gọi nó. Một khi bạn có đại biểu của bạn, bạn có các tùy chọn hạn chế trong việc kiểm tra những gì nó làm và không có gì.

Bằng cách lưu trữ lambda làm biểu thức, bạn đang lưu trữ cây biểu thị đại diện cho đại biểu. Nó có thể được thao tác để làm những việc khác như thay đổi các tham số của nó, thay đổi cơ thể và làm cho nó làm điều gì đó hoàn toàn khác biệt. Nó thậm chí có thể được biên dịch lại cho một đại biểu để bạn có thể gọi nó nếu bạn muốn. Bạn có thể dễ dàng kiểm tra biểu thức để xem các thông số của nó là gì, nó hoạt động như thế nào và nó hoạt động như thế nào. Đây là điều mà một nhà cung cấp truy vấn có thể sử dụng để hiểu và dịch một biểu thức sang một ngôn ngữ khác (chẳng hạn như viết một truy vấn SQL cho một cây biểu thức tương ứng).

Cũng dễ dàng hơn cả việc tạo đại biểu động bằng cách sử dụng biểu thức hơn là phát ra mã. Bạn có thể nghĩ mã của bạn ở mức cao hơn như các biểu thức rất giống với cách trình biên dịch xem mã thay vì đi mức thấp và xem mã của bạn như là các chỉ dẫn IL.

Vì vậy, với biểu thức, bạn có thể làm được nhiều hơn một đại biểu ẩn danh đơn giản. Mặc dù nó không thực sự miễn phí, hiệu suất sẽ mất một hit nếu bạn chạy biểu thức biên dịch so với một phương pháp thông thường hoặc một đại biểu vô danh. Nhưng đó có thể không phải là vấn đề vì lợi ích khác của việc sử dụng các biểu thức có thể quan trọng đối với bạn.

+0

Điều này làm rõ nó hoàn hảo cho tôi, cảm ơn rất nhiều :-) – Steffen

13

Func<> chỉ là một loại đại biểu. Biểu thức một biểu diễn thời gian chạy của cây hoàn chỉnh của operations, tùy chọn, có thể được biên dịch trong thời gian chạy vào một đại biểu. Đó là cây được phân tích cú pháp bởi các trình phân tích cú pháp biểu thức như Linq-to-SQL để tạo ra các câu lệnh SQL hoặc làm những thứ thông minh khác. Khi bạn gán một lambda cho một loại Expression, trình biên dịch tạo ra cây biểu thức này cũng như mã IL thông thường. More on expression trees.

4

Cung cấp lớp cơ sở mà từ đó các lớp đại diện cho các nút cây biểu thị .

System.Linq.Expressions.BinaryExpression 
System.Linq.Expressions.BlockExpression 
System.Linq.Expressions.ConditionalExpression 
System.Linq.Expressions.ConstantExpression 
System.Linq.Expressions.DebugInfoExpression 
System.Linq.Expressions.DefaultExpression 
System.Linq.Expressions.DynamicExpression 
System.Linq.Expressions.GotoExpression 
System.Linq.Expressions.IndexExpression 
System.Linq.Expressions.InvocationExpression 
System.Linq.Expressions.LabelExpression 
System.Linq.Expressions.LambdaExpression 
System.Linq.Expressions.ListInitExpression 
System.Linq.Expressions.LoopExpression 
System.Linq.Expressions.MemberExpression 
System.Linq.Expressions.MemberInitExpression 
System.Linq.Expressions.MethodCallExpression 
System.Linq.Expressions.NewArrayExpression 
System.Linq.Expressions.NewExpression 
System.Linq.Expressions.ParameterExpression 
System.Linq.Expressions.RuntimeVariablesExpression 
System.Linq.Expressions.SwitchExpression 
System.Linq.Expressions.TryExpression 
System.Linq.Expressions.TypeBinaryExpression 
System.Linq.Expressions.UnaryExpression 

http://msdn.microsoft.com/en-us/library/system.linq.expressions.expression.aspx

cây biểu thức đại diện cho biểu LINQ có thể được phân tích và ví dụ biến thành truy vấn SQL.

4

Expression Trees cho phép bạn kiểm tra mã bên trong biểu thức, trong mã của bạn.

Ví dụ: nếu bạn chuyển biểu thức này: o => o.Name, mã của bạn có thể phát hiện ra rằng thuộc tính Name đã được truy cập bên trong biểu thức.

9

Để minh họa cho câu trả lời khác, nếu bạn biên dịch những 2 biểu thức và có cái nhìn tại các trình biên dịch tạo ra mã, này tôi những gì bạn sẽ thấy:

Func<int, bool> Is42 = (value) => value == 42;

Func<int, bool> Is42 = new Func<int, bool>((@value) => value == 42); 


Expression<Func<int, bool>> Is42 = (value) => value == 42;

ParameterExpression[] parameterExpressionArray; 
ParameterExpression parameterExpression = Expression.Parameter(typeof(int), "value"); 
Expression<Func<int, bool>> Is42 = Expression.Lambda<Func<int, bool>>(Expression.Equal(parameterExpression, Expression.Constant(42, typeof(int))), new ParameterExpression[] { parameterExpression }); 
+0

Ok, điểm mà bạn đang cố gắng thực hiện ? – Phil

+4

Ông đã hỏi những khác biệt và mã được tạo ra là gì để giải thích sự khác biệt. – Ucodia

2

Để bất cứ điều gì khác đã viết (đó là hoàn toàn chính xác) Tôi sẽ thêm rằng thông qua các lớp học Expression bạn có thể tạo ra các phương pháp mới trong thời gian chạy. Có một số giới hạn. Không phải tất cả những gì bạn có thể làm trong C# có thể được thực hiện trong một cây Expression (ít nhất là trong .NET 3.5. Với .NET 4.0, chúng đã thêm một số lượng lớn có thể là Expression "loại"). Việc sử dụng điều này có thể là (ví dụ) để tạo truy vấn động và chuyển nó tới LINQ-to-SQL hoặc thực hiện lọc dựa trên đầu vào của người dùng ... (bạn luôn có thể làm điều này với CodeDom nếu tất cả những gì bạn muốn là một phương pháp động không tương thích với LINQ-to-SQL, nhưng phát ra mã IL trực tiếp là khá khó khăn :-))

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