Trong C# với .NET 3.5, bạn có thể sử dụng Expression
cho việc này; bạn có thể xây dựng một biểu thức được tham số hóa và sau đó biên dịch nó thành một đại biểu. Đây chính xác là những gì tôi đã làm cho khía cạnh toán học của Finguistics. Tôi vẫn có mã phân tích mà tôi đã sử dụng nếu bạn muốn ...
Bí quyết chính mà tôi đã sử dụng là giữ cho loại đại biểu được biết, tôi đã sử dụng mảng làm loại đầu vào - xử lý các arg khác nhau như arr [0] , arr 1, arr [2] v.v. Điều này có nghĩa là tôi có thể biên dịch thành (ví dụ) Func<decimal[], decimal>
(mất một mảng là decimal
s, trả lại một decimal
).
Khi bạn đã gọi số Compile()
, điều này rất nguy hiểm như thể bạn đã có mã để thực hiện trực tiếp.
(chỉnh sửa)
Là một ví dụ ngắn gọn của việc sử dụng Expression
theo cách này (với một chức năng mã hóa cứng), xem dưới đây. Trình phân tích cú pháp tôi đã viết hiện tại là hoạt động như một biến vị ngữ - tức là để kiểm tra xem "? + (2 *? -?) = 22 +?" - nhưng sẽ không khó thay đổi nó để trả về kết quả thay thế (và giới thiệu nhiều hoạt động hơn, như sin
/pow
/etc - có lẽ bằng cách ánh xạ chúng trực tiếp tới các phương thức công khai trên đối tượng trợ giúp (qua Expression.Call
)).
using System;
using System.Linq.Expressions;
static class Program
{
static void Main()
{
var args = Expression.Parameter(typeof(float[]), "args");
var x = Expression.ArrayIndex(args, Expression.Constant(0));
var y = Expression.ArrayIndex(args, Expression.Constant(1));
var add = Expression.Add(x, y);
var lambda = Expression.Lambda<Func<float[], float>>(add, args);
Func<float[], float> func = lambda.Compile();
Console.WriteLine(func.Call(1, 2));
Console.WriteLine(func.Call(3, 4));
Console.WriteLine(func.Call(5, 6));
}
static T Call<T>(this Func<T[], T> func, params T[] args)
{ // just allows "params" usage...
return func(args);
}
}
Nguồn
2009-02-21 10:59:16
Biểu thức phức tạp như thế nào? Giới hạn trong bốn hàm số học, hoặc rất chung chung? – Richard
Có thể khá phức tạp, bao gồm các hàm có nhiều tham số. – Steve