public static class ExprOp {
static public Func<Expression, Expression> Visit =
FuncOp.Create<Expression, Expression>(
(self, expr) => {
if (expr == null) {
	return expr;
}
switch (expr.NodeType) {
case ExpressionType.Coalesce:
var c = (BinaryExpression) expr;
var left = self(c.Left);
var right = self(c.Right);
var conv = self(c.Conversion);
return (left == c.Left
&& right == c.Right
&& conv == c.Conversion)
? expr
: Expression.Coalesce(
left,
right,
(LambdaExpression) conv);
case ExpressionType.Conditional:
var ce = (ConditionalExpression) expr;
var t = self(ce.Test);
var it = self(ce.IfTrue);
var @if = self(ce.IfFalse);
return (t == ce.Test
&& it == ce.IfTrue
&& @if == ce.IfFalse)
? expr
: Expression.Condition(t, it, @if);
// Kd pro ostatn ppady byl vynechn.
// Oeten jsou tyto typy:
// ExpressionType.TypeIs
// ExpressionType.MemberAccess
// ExpressionType.Call
// ExpressionType.Lambda
// ExpressionType.New
// ExpressionType.NewArrayInit
// ExpressionType.NewArrayBounds
// ExpressionType.Invoke
// ExpressionType.MemberInit
// ExpressionType.ListInit
// Nen zde dn vtev default, take vechny ostatn typy
// uzl nezpracovv tento pkaz switch, ale
// zachycuj je pkazy if 
// za pkazem switch.
}
if (expr.IsBinary()) {
var b = (BinaryExpression) expr;
var left = self(b.Left);
var right = self(b.Right);
return (left == b.Left && right == b.Right)
? expr
: Expression.MakeBinary(
expr.NodeType,
left,
right);
}
else if (expr.IsUnary()) {
var u = (UnaryExpression) expr;
var op = self(u.Operand);
return (u.Operand == op)
? expr
: Expression.MakeUnary(
u.NodeType,
op,
expr.Type);
}
return expr;
}
)
public static bool IsBinary(this Expression expr) {
	return expr is BinaryExpression;
}
public static bool IsUnary(this Expression expr) {
	return expr is UnaryExpression;
}
// zbytek kdu vynechn ...
}
