Tôi muốn nóiTôi có thể chụp một biến cục bộ thành một biểu thức LINQ như một hằng số thay vì một tham chiếu đóng không?
int x = magic(), y = moremagic();
return i => i + (x/y);
và có x được chụp như một hằng số thay vì một tài liệu tham khảo khác nhau. Ý tưởng là x sẽ không bao giờ thay đổi và do đó khi biểu thức được biên dịch, trình biên dịch có thể làm việc gấp liên tục và tạo mã hiệu quả hơn - tức là tính x/y
một lần thay vì trên mọi cuộc gọi, thông qua các tham chiếu con trỏ vào bản ghi đóng.
Không có cách nào để đánh dấu x là chỉ đọc trong một phương thức và trình biên dịch không đủ thông minh để phát hiện rằng nó không thay đổi sau khi tạo biểu thức.
Tôi ghét phải xây dựng biểu thức bằng tay. Có ý tưởng tuyệt vời nào không?
CẬP NHẬT: Tôi đã kết thúc bằng cách sử dụng tuyệt vời LinqKit để xây dựng một bộ đánh giá một phần sẽ thực hiện các thay thế mà tôi muốn. Biến đổi chỉ an toàn nếu bạn biết rằng các tài liệu tham khảo có liên quan sẽ không thay đổi, nhưng nó hoạt động cho mục đích của tôi. Có thể hạn chế việc đánh giá từng phần chỉ để các thành viên trực tiếp đóng cửa của bạn, mà bạn kiểm soát, bằng cách thêm một kiểm tra thêm hoặc hai trong đó, đó là khá rõ ràng về kiểm tra mã mẫu được cung cấp trong LinqKit.
/// <summary>Walks your expression and eagerly evaluates property/field members and substitutes them with constants.
/// You must be sure this is semantically correct, by ensuring those fields (e.g. references to captured variables in your closure)
/// will never change, but it allows the expression to be compiled more efficiently by turning constant numbers into true constants,
/// which the compiler can fold.</summary>
public class PartiallyEvaluateMemberExpressionsVisitor : ExpressionVisitor
{
protected override Expression VisitMemberAccess(MemberExpression m)
{
Expression exp = this.Visit(m.Expression);
if (exp == null || exp is ConstantExpression) // null=static member
{
object @object = exp == null ? null : ((ConstantExpression)exp).Value;
object value = null; Type type = null;
if (m.Member is FieldInfo)
{
FieldInfo fi = (FieldInfo)m.Member;
value = fi.GetValue(@object);
type = fi.FieldType;
}
else if (m.Member is PropertyInfo)
{
PropertyInfo pi = (PropertyInfo)m.Member;
if (pi.GetIndexParameters().Length != 0)
throw new ArgumentException("cannot eliminate closure references to indexed properties");
value = pi.GetValue(@object, null);
type = pi.PropertyType;
}
return Expression.Constant(value, type);
}
else // otherwise just pass it through
{
return Expression.MakeMemberAccess(exp, m.Member);
}
}
}
chỉ là những gì tôi đang tìm kiếm! – jeroenh
Tôi biết nó đã được một thời gian, nhưng điều này đã giúp tôi tiết kiệm rất nhiều thời gian. Cảm ơn. – Stargazer