Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I combine several Expressions into a fast method?

Suppose I have the following expressions:

Expression<Action<T, StringBuilder>> expr1 = (t, sb) => sb.Append(t.Name);
Expression<Action<T, StringBuilder>> expr2 = (t, sb) => sb.Append(", ");
Expression<Action<T, StringBuilder>> expr3 = (t, sb) => sb.Append(t.Description);

I'd like to be able to compile these into a method/delegate equivalent to the following:

void Method(T t, StringBuilder sb) 
{
    sb.Append(t.Name);
    sb.Append(", ");
    sb.Append(t.Description);
}

What is the best way to approach this? I'd like it to perform well, ideally with performance equivalent to the above method.

UPDATE So, whilst it appears that there is no way to do this directly in C#3 is there a way to convert an expression to IL so that I can use it with System.Reflection.Emit?

like image 468
chillitom Avatar asked Mar 10 '10 17:03

chillitom


1 Answers

Unfortunately in .NET 3.5 you cannot build an expression which performs a series of arbitrary operations. Here's the list of supported expressions:

  • Arithmetic: Add, AddChecked, Divide, Modulo, Multiply, MultiplyChecked, Negate, NegateChecked, Power, Subtract, SubtractChecked, UnaryPlus
  • Creation: Bind, ElementInit, ListBind, ListInit, MemberBind, MemberInit, New, NewArrayBounds, NewArrayInit
  • Bitwise: And, ExclusiveOr, LeftShift (<<), Not, Or, RightShift (>>)
  • Logical: AndAlso (&&), Condition (? :), Equal, GreaterThan, GreaterThanOrEqual, LessThan, * LessThanOrEqual, NotEqual, OrElse (||), TypeIs
  • Member Access: ArrayIndex, ArrayLength, Call, Field, Property, PropertyOrField
  • Other: Convert, ConvertChecked, Coalesce (??), Constant, Invoke, Lambda, Parameter, TypeAs, Quote

.NET 4 extends this API by adding the following expressions:

  • Mutation: AddAssign, AddAssignChecked, AndAssign, Assign, DivideAssign, ExclusiveOrAssign, LeftShiftAssign, ModuloAssign, MultiplyAssign, MultiplyAssignChecked, OrAssign, PostDecrementAssign, PostIncrementAssign, PowerAssign, PreDecrementAssign, PreIncrementAssign, RightShiftAssign, SubtractAssign, SubtractAssignChecked
  • Arithmetic: Decrement, Default, Increment, OnesComplement
  • Member Access: ArrayAccess, Dynamic
  • Logical: ReferenceEqual, ReferenceNotEqual, TypeEqual
  • Flow: Block, Break, Continue, Empty, Goto, IfThen, IfThenElse, IfFalse, IfTrue, Label, Loop, Return, Switch, SwitchCase, Unbox, Variable
  • Exceptions: Catch, Rethrow, Throw
  • Debug: ClearDebugInfo, DebugInfo

The Block expression is particularly interesting.

like image 178
Darin Dimitrov Avatar answered Oct 04 '22 08:10

Darin Dimitrov