2012-02-26 40 views
8

Tôi có biểu hiện này:Hiểu nhầm cây biên soạn?

Expression<Func<string, bool>> f = s => s.Length < 5; 

enter image description here

ParameterExpression p = Expression.Parameter (typeof (string), "s"); 
MemberExpression stringLength = Expression.Property (p, "Length"); 
ConstantExpression five = Expression.Constant (5); 
BinaryExpression comparison = Expression.LessThan (stringLength, five); 
Expression<Func<string, bool>> lambda= Expression.Lambda<Func<string, bool>> (comparison, p); 

// phép: test

Func<string, bool> runnable = lambda.Compile(); 
Console.WriteLine (runnable ("kangaroo")); // False 
Console.WriteLine (runnable ("dog")); //True 

Tôi muốn hỏi về .Compile()

nó biên dịch gì? Và sự khác biệt giữa việc thực hiện đầu tiên và thực thi sau này là gì ...?

Biên dịch phải là điều gì đó xảy ra một lần và không xảy ra lại sau ....

Điều gì sẽ giúp tôi như thế nào?

+4

Bạn đã sử dụng công cụ nào để tạo hình ảnh biểu đồ cây biểu thức này? – Anastasiosyal

+2

@Anastasiosyal của nó từ một cuốn sách http://i.stack.imgur.com/Y5ejU.jpg –

+1

Ah, tôi hiểu rồi, tôi nghĩ rằng tôi đã thiếu một vài người quan sát tuyệt vời trong một khoảnh khắc. Tôi đoán, cũng có [trình bày hình ảnh cây wpf] (http://www.codeproject.com/Articles/83465/ExpressionTree-Visualizer-in-WPF) bởi @gcvcdcamp. Một dự án thú vị có thể là để hỗ trợ hiển thị cây biểu thức dưới dạng đồ thị bằng cách sử dụng một cái gì đó như [Đồ thị #] (http: //graphsharp.codeplex.com /) mặc dù tôi có thể thấy một biểu đồ như vậy có thể trở nên rất bận rộn một cách nhanh chóng với bất kỳ biểu hiện không tầm thường nào. – Anastasiosyal

Trả lời

9

Khi bạn xây dựng cây biểu thức trong thời gian chạy, không có mã nào được phát ra. Đó là một cách để đại diện cho mã .NET khi chạy.

Khi bạn gọi phương thức .Compile trên cây biểu thức, mã IL thực được phát ra để chuyển đổi cây biểu thức này thành đại biểu (Func<string, bool> trong trường hợp của bạn) mà bạn có thể gọi khi chạy. Vì vậy, mã mà cây biểu thức này đại diện có thể được thực hiện chỉ sau khi bạn biên dịch nó.

Dịch vụ gọi điện là một hoạt động tốn kém. Về cơ bản bạn nên gọi nó một lần và sau đó bộ nhớ đệm đại biểu kết quả mà bạn có thể sử dụng để gọi mã nhiều lần.

+0

Trong trường hợp "REAL" nào tôi sẽ sử dụng nó? ok ... vì vậy im xây dựng biểu hiện tại thời gian chạy, nhưng nó khó khăn hơn nhiều và sẽ chứa rất nhiều IF (để xây dựng nó) .... bạn có thể vui lòng chỉnh sửa với kịch bản thực sự mà tôi cần động BUILD một biểu hiện? –

+0

Ý bạn là câu đầu tiên? Bạn có nghĩa là tất cả 5 dòng mã trong ví dụ đầu tiên sẽ không có mã IL, nhưng sẽ được chuyển đổi thành Tree Expression trực tiếp? Tôi không tin rằng trình biên dịch tối ưu hóa như thế này. – Euphoric

2

Expression<Func<string,bool>> chỉ là một biểu tượng của một biểu thức, không thể là được thực hiện. Gọi số Compile() cung cấp cho bạn một đại biểu được biên soạn, một đoạn mã mà bạn có thể gọi. Về cơ bản, chương trình của bạn soạn một đoạn mã nhỏ khi chạy và sau đó gọi nó như thể nó được trình biên dịch xử lý. Đây là những gì hai dòng mã cuối cùng của bạn làm: như bạn có thể thấy, đoạn mã được biên dịch có thể phân tích độ dài của chuỗi mà bạn truyền vào - khi độ dài nhỏ hơn năm, bạn sẽ nhận được True quay lại; khi năm tuổi trở lên, bạn sẽ nhận được False.

Điều gì sẽ xảy ra khi thực thi đầu tiên đoạn mã được biên dịch phụ thuộc vào nền tảng và không được phát hiện bởi các lập trình viên sử dụng nền tảng .NET.

2

Compile() lấy cây biểu thức (biểu diễn dữ liệu của một số lôgic) và chuyển đổi thành IL mà sau đó có thể được thực hiện trực tiếp dưới dạng đại biểu.

Sự khác biệt duy nhất giữa lần thực hiện đầu tiên và thực thi sau đó là khả năng Compile() sẽ không kích hoạt trình biên dịch JIT từ IL sang mã bộ xử lý riêng. Điều đó có thể xảy ra khi thực hiện lần đầu tiên.