测试lambda表达式相等性的最有效方法

测试lambda表达式相等性的最有效方法

给定方法签名:

public bool AreTheSame<T>(Expression<Func<T, object>> exp1, Expression<Func<T, object>> exp2)

如果两个表达式相同,最有效的方法是什么?这只需要适用于简单的表达式,我的意思是所有“支持”的都是简单的MemberExpressions,例如c => c.ID.

一个示例调用可能是:

AreTheSame<User>(u1 => u1.ID, u2 => u2.ID); --> would return true


德玛西亚99
浏览 859回答 3
3回答

ABOUTYOU

更新:由于我的解决方案的兴趣,我已经更新了代码,因此它支持数组,新运算符和其他东西,并以更优雅的方式比较AST。这是Marc代码的改进版本,现在可以作为nuget包使用:public&nbsp;static&nbsp;class&nbsp;LambdaCompare{ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;bool&nbsp;Eq<TSource,&nbsp;TValue>( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Expression<Func<TSource,&nbsp;TValue>>&nbsp;x, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Expression<Func<TSource,&nbsp;TValue>>&nbsp;y) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;ExpressionsEqual(x,&nbsp;y,&nbsp;null,&nbsp;null); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;bool&nbsp;Eq<TSource1,&nbsp;TSource2,&nbsp;TValue>( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Expression<Func<TSource1,&nbsp;TSource2,&nbsp;TValue>>&nbsp;x, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Expression<Func<TSource1,&nbsp;TSource2,&nbsp;TValue>>&nbsp;y) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;ExpressionsEqual(x,&nbsp;y,&nbsp;null,&nbsp;null); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;Expression<Func<Expression<Func<TSource,&nbsp;TValue>>,&nbsp;bool>>&nbsp;Eq<TSource,&nbsp;TValue>(Expression<Func<TSource,&nbsp;TValue>>&nbsp;y) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;x&nbsp;=>&nbsp;ExpressionsEqual(x,&nbsp;y,&nbsp;null,&nbsp;null); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;bool&nbsp;ExpressionsEqual(Expression&nbsp;x,&nbsp;Expression&nbsp;y,&nbsp;LambdaExpression&nbsp;rootX,&nbsp;LambdaExpression&nbsp;rootY) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(ReferenceEquals(x,&nbsp;y))&nbsp;return&nbsp;true; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(x&nbsp;==&nbsp;null&nbsp;||&nbsp;y&nbsp;==&nbsp;null)&nbsp;return&nbsp;false; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;valueX&nbsp;=&nbsp;TryCalculateConstant(x); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;valueY&nbsp;=&nbsp;TryCalculateConstant(y); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(valueX.IsDefined&nbsp;&&&nbsp;valueY.IsDefined) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;ValuesEqual(valueX.Value,&nbsp;valueY.Value); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(x.NodeType&nbsp;!=&nbsp;y.NodeType &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;||&nbsp;x.Type&nbsp;!=&nbsp;y.Type) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(IsAnonymousType(x.Type)&nbsp;&&&nbsp;IsAnonymousType(y.Type)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;NotImplementedException("Comparison&nbsp;of&nbsp;Anonymous&nbsp;Types&nbsp;is&nbsp;not&nbsp;supported"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;false; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(x&nbsp;is&nbsp;LambdaExpression) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;lx&nbsp;=&nbsp;(LambdaExpression)x; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;ly&nbsp;=&nbsp;(LambdaExpression)y; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;paramsX&nbsp;=&nbsp;lx.Parameters; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;paramsY&nbsp;=&nbsp;ly.Parameters; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;CollectionsEqual(paramsX,&nbsp;paramsY,&nbsp;lx,&nbsp;ly)&nbsp;&&&nbsp;ExpressionsEqual(lx.Body,&nbsp;ly.Body,&nbsp;lx,&nbsp;ly); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(x&nbsp;is&nbsp;MemberExpression) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;mex&nbsp;=&nbsp;(MemberExpression)x; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;mey&nbsp;=&nbsp;(MemberExpression)y; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Equals(mex.Member,&nbsp;mey.Member)&nbsp;&&&nbsp;ExpressionsEqual(mex.Expression,&nbsp;mey.Expression,&nbsp;rootX,&nbsp;rootY); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(x&nbsp;is&nbsp;BinaryExpression) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;bx&nbsp;=&nbsp;(BinaryExpression)x; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;by&nbsp;=&nbsp;(BinaryExpression)y; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;bx.Method&nbsp;==&nbsp;@by.Method&nbsp;&&&nbsp;ExpressionsEqual(bx.Left,&nbsp;@by.Left,&nbsp;rootX,&nbsp;rootY)&nbsp;&& &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExpressionsEqual(bx.Right,&nbsp;@by.Right,&nbsp;rootX,&nbsp;rootY); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(x&nbsp;is&nbsp;UnaryExpression) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;ux&nbsp;=&nbsp;(UnaryExpression)x; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;uy&nbsp;=&nbsp;(UnaryExpression)y; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;ux.Method&nbsp;==&nbsp;uy.Method&nbsp;&&&nbsp;ExpressionsEqual(ux.Operand,&nbsp;uy.Operand,&nbsp;rootX,&nbsp;rootY); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(x&nbsp;is&nbsp;ParameterExpression) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;px&nbsp;=&nbsp;(ParameterExpression)x; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;py&nbsp;=&nbsp;(ParameterExpression)y; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;rootX.Parameters.IndexOf(px)&nbsp;==&nbsp;rootY.Parameters.IndexOf(py); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(x&nbsp;is&nbsp;MethodCallExpression) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;cx&nbsp;=&nbsp;(MethodCallExpression)x; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;cy&nbsp;=&nbsp;(MethodCallExpression)y; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;cx.Method&nbsp;==&nbsp;cy.Method &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&&&nbsp;ExpressionsEqual(cx.Object,&nbsp;cy.Object,&nbsp;rootX,&nbsp;rootY) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&&&nbsp;CollectionsEqual(cx.Arguments,&nbsp;cy.Arguments,&nbsp;rootX,&nbsp;rootY); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(x&nbsp;is&nbsp;MemberInitExpression) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;mix&nbsp;=&nbsp;(MemberInitExpression)x; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;miy&nbsp;=&nbsp;(MemberInitExpression)y; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;ExpressionsEqual(mix.NewExpression,&nbsp;miy.NewExpression,&nbsp;rootX,&nbsp;rootY) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&&&nbsp;MemberInitsEqual(mix.Bindings,&nbsp;miy.Bindings,&nbsp;rootX,&nbsp;rootY); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(x&nbsp;is&nbsp;NewArrayExpression) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;nx&nbsp;=&nbsp;(NewArrayExpression)x; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;ny&nbsp;=&nbsp;(NewArrayExpression)y; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;CollectionsEqual(nx.Expressions,&nbsp;ny.Expressions,&nbsp;rootX,&nbsp;rootY); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(x&nbsp;is&nbsp;NewExpression) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;nx&nbsp;=&nbsp;(NewExpression)x; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;ny&nbsp;=&nbsp;(NewExpression)y; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Equals(nx.Constructor,&nbsp;ny.Constructor) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&&&nbsp;CollectionsEqual(nx.Arguments,&nbsp;ny.Arguments,&nbsp;rootX,&nbsp;rootY) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&&&nbsp;(nx.Members&nbsp;==&nbsp;null&nbsp;&&&nbsp;ny.Members&nbsp;==&nbsp;null &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;||&nbsp;nx.Members&nbsp;!=&nbsp;null&nbsp;&&&nbsp;ny.Members&nbsp;!=&nbsp;null&nbsp;&&&nbsp;CollectionsEqual(nx.Members,&nbsp;ny.Members)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(x&nbsp;is&nbsp;ConditionalExpression) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;cx&nbsp;=&nbsp;(ConditionalExpression)x; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;cy&nbsp;=&nbsp;(ConditionalExpression)y; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExpressionsEqual(cx.Test,&nbsp;cy.Test,&nbsp;rootX,&nbsp;rootY) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&&&nbsp;ExpressionsEqual(cx.IfFalse,&nbsp;cy.IfFalse,&nbsp;rootX,&nbsp;rootY) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&&&nbsp;ExpressionsEqual(cx.IfTrue,&nbsp;cy.IfTrue,&nbsp;rootX,&nbsp;rootY); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;NotImplementedException(x.ToString()); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;Boolean&nbsp;IsAnonymousType(Type&nbsp;type) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Boolean&nbsp;hasCompilerGeneratedAttribute&nbsp;=&nbsp;type.GetCustomAttributes(typeof(CompilerGeneratedAttribute),&nbsp;false).Any(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Boolean&nbsp;nameContainsAnonymousType&nbsp;=&nbsp;type.FullName.Contains("AnonymousType"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Boolean&nbsp;isAnonymousType&nbsp;=&nbsp;hasCompilerGeneratedAttribute&nbsp;&&&nbsp;nameContainsAnonymousType; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;isAnonymousType; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;bool&nbsp;MemberInitsEqual(ICollection<MemberBinding>&nbsp;bx,&nbsp;ICollection<MemberBinding>&nbsp;by,&nbsp;LambdaExpression&nbsp;rootX,&nbsp;LambdaExpression&nbsp;rootY) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(bx.Count&nbsp;!=&nbsp;by.Count) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;false; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(bx.Concat(by).Any(b&nbsp;=>&nbsp;b.BindingType&nbsp;!=&nbsp;MemberBindingType.Assignment)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;NotImplementedException("Only&nbsp;MemberBindingType.Assignment&nbsp;is&nbsp;supported"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bx.Cast<MemberAssignment>().OrderBy(b&nbsp;=>&nbsp;b.Member.Name).Select((b,&nbsp;i)&nbsp;=>&nbsp;new&nbsp;{&nbsp;Expr&nbsp;=&nbsp;b.Expression,&nbsp;b.Member,&nbsp;Index&nbsp;=&nbsp;i&nbsp;}) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.Join( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;by.Cast<MemberAssignment>().OrderBy(b&nbsp;=>&nbsp;b.Member.Name).Select((b,&nbsp;i)&nbsp;=>&nbsp;new&nbsp;{&nbsp;Expr&nbsp;=&nbsp;b.Expression,&nbsp;b.Member,&nbsp;Index&nbsp;=&nbsp;i&nbsp;}), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;o&nbsp;=>&nbsp;o.Index,&nbsp;o&nbsp;=>&nbsp;o.Index,&nbsp;(xe,&nbsp;ye)&nbsp;=>&nbsp;new&nbsp;{&nbsp;XExpr&nbsp;=&nbsp;xe.Expr,&nbsp;XMember&nbsp;=&nbsp;xe.Member,&nbsp;YExpr&nbsp;=&nbsp;ye.Expr,&nbsp;YMember&nbsp;=&nbsp;ye.Member&nbsp;}) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.All(o&nbsp;=>&nbsp;Equals(o.XMember,&nbsp;o.YMember)&nbsp;&&&nbsp;ExpressionsEqual(o.XExpr,&nbsp;o.YExpr,&nbsp;rootX,&nbsp;rootY)); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;bool&nbsp;ValuesEqual(object&nbsp;x,&nbsp;object&nbsp;y) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(ReferenceEquals(x,&nbsp;y)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(x&nbsp;is&nbsp;ICollection&nbsp;&&&nbsp;y&nbsp;is&nbsp;ICollection) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;CollectionsEqual((ICollection)x,&nbsp;(ICollection)y); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Equals(x,&nbsp;y); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;ConstantValue&nbsp;TryCalculateConstant(Expression&nbsp;e) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(e&nbsp;is&nbsp;ConstantExpression) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;ConstantValue(true,&nbsp;((ConstantExpression)e).Value); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(e&nbsp;is&nbsp;MemberExpression) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;me&nbsp;=&nbsp;(MemberExpression)e; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;parentValue&nbsp;=&nbsp;TryCalculateConstant(me.Expression); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(parentValue.IsDefined) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;result&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;me.Member&nbsp;is&nbsp;FieldInfo &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;((FieldInfo)me.Member).GetValue(parentValue.Value) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;((PropertyInfo)me.Member).GetValue(parentValue.Value); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;ConstantValue(true,&nbsp;result); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(e&nbsp;is&nbsp;NewArrayExpression) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;ae&nbsp;=&nbsp;((NewArrayExpression)e); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;result&nbsp;=&nbsp;ae.Expressions.Select(TryCalculateConstant); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(result.All(i&nbsp;=>&nbsp;i.IsDefined)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;ConstantValue(true,&nbsp;result.Select(i&nbsp;=>&nbsp;i.Value).ToArray()); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(e&nbsp;is&nbsp;ConditionalExpression) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;ce&nbsp;=&nbsp;(ConditionalExpression)e; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;evaluatedTest&nbsp;=&nbsp;TryCalculateConstant(ce.Test); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(evaluatedTest.IsDefined) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TryCalculateConstant(Equals(evaluatedTest.Value,&nbsp;true)&nbsp;?&nbsp;ce.IfTrue&nbsp;:&nbsp;ce.IfFalse); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;default(ConstantValue); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;bool&nbsp;CollectionsEqual(IEnumerable<Expression>&nbsp;x,&nbsp;IEnumerable<Expression>&nbsp;y,&nbsp;LambdaExpression&nbsp;rootX,&nbsp;LambdaExpression&nbsp;rootY) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;x.Count()&nbsp;==&nbsp;y.Count() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&&&nbsp;x.Select((e,&nbsp;i)&nbsp;=>&nbsp;new&nbsp;{&nbsp;Expr&nbsp;=&nbsp;e,&nbsp;Index&nbsp;=&nbsp;i&nbsp;}) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.Join(y.Select((e,&nbsp;i)&nbsp;=>&nbsp;new&nbsp;{&nbsp;Expr&nbsp;=&nbsp;e,&nbsp;Index&nbsp;=&nbsp;i&nbsp;}), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;o&nbsp;=>&nbsp;o.Index,&nbsp;o&nbsp;=>&nbsp;o.Index,&nbsp;(xe,&nbsp;ye)&nbsp;=>&nbsp;new&nbsp;{&nbsp;X&nbsp;=&nbsp;xe.Expr,&nbsp;Y&nbsp;=&nbsp;ye.Expr&nbsp;}) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.All(o&nbsp;=>&nbsp;ExpressionsEqual(o.X,&nbsp;o.Y,&nbsp;rootX,&nbsp;rootY)); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;bool&nbsp;CollectionsEqual(ICollection&nbsp;x,&nbsp;ICollection&nbsp;y) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;x.Count&nbsp;==&nbsp;y.Count &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&&&nbsp;x.Cast<object>().Select((e,&nbsp;i)&nbsp;=>&nbsp;new&nbsp;{&nbsp;Expr&nbsp;=&nbsp;e,&nbsp;Index&nbsp;=&nbsp;i&nbsp;}) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.Join(y.Cast<object>().Select((e,&nbsp;i)&nbsp;=>&nbsp;new&nbsp;{&nbsp;Expr&nbsp;=&nbsp;e,&nbsp;Index&nbsp;=&nbsp;i&nbsp;}), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;o&nbsp;=>&nbsp;o.Index,&nbsp;o&nbsp;=>&nbsp;o.Index,&nbsp;(xe,&nbsp;ye)&nbsp;=>&nbsp;new&nbsp;{&nbsp;X&nbsp;=&nbsp;xe.Expr,&nbsp;Y&nbsp;=&nbsp;ye.Expr&nbsp;}) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.All(o&nbsp;=>&nbsp;Equals(o.X,&nbsp;o.Y)); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;struct&nbsp;ConstantValue &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;ConstantValue(bool&nbsp;isDefined,&nbsp;object&nbsp;value) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;this() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IsDefined&nbsp;=&nbsp;isDefined; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Value&nbsp;=&nbsp;value; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;bool&nbsp;IsDefined&nbsp;{&nbsp;get;&nbsp;private&nbsp;set;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;object&nbsp;Value&nbsp;{&nbsp;get;&nbsp;private&nbsp;set;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}}请注意,它不会比较完整的AST。相反,它会折叠常量表达式并比较它们的值而不是它们的AST。当lambda具有对局部变量的引用时,它对于模拟验证很有用。在他的情况下,变量通过其值进行比较。单元测试:[TestClass]public&nbsp;class&nbsp;Tests{ &nbsp;&nbsp;&nbsp;&nbsp;[TestMethod] &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;BasicConst() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;f1&nbsp;=&nbsp;GetBasicExpr1(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;f2&nbsp;=&nbsp;GetBasicExpr2(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Assert.IsTrue(LambdaCompare.Eq(f1,&nbsp;f2)); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;[TestMethod] &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;PropAndMethodCall() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;f1&nbsp;=&nbsp;GetPropAndMethodExpr1(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;f2&nbsp;=&nbsp;GetPropAndMethodExpr2(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Assert.IsTrue(LambdaCompare.Eq(f1,&nbsp;f2)); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;[TestMethod] &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;MemberInitWithConditional() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;f1&nbsp;=&nbsp;GetMemberInitExpr1(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;f2&nbsp;=&nbsp;GetMemberInitExpr2(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Assert.IsTrue(LambdaCompare.Eq(f1,&nbsp;f2)); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;[TestMethod] &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;AnonymousType() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;f1&nbsp;=&nbsp;GetAnonymousExpr1(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;f2&nbsp;=&nbsp;GetAnonymousExpr2(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Assert.Inconclusive("Anonymous&nbsp;Types&nbsp;are&nbsp;not&nbsp;supported"); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;Expression<Func<int,&nbsp;string,&nbsp;string>>&nbsp;GetBasicExpr2() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;const2&nbsp;=&nbsp;"some&nbsp;const&nbsp;value"; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;const3&nbsp;=&nbsp;"{0}{1}{2}{3}"; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(i,&nbsp;s)&nbsp;=> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string.Format(const3,&nbsp;(i&nbsp;+&nbsp;25).ToString(CultureInfo.InvariantCulture),&nbsp;i&nbsp;+&nbsp;s,&nbsp;const2.ToUpper(),&nbsp;25); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;Expression<Func<int,&nbsp;string,&nbsp;string>>&nbsp;GetBasicExpr1() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;const1&nbsp;=&nbsp;25; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(first,&nbsp;second)&nbsp;=> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string.Format("{0}{1}{2}{3}",&nbsp;(first&nbsp;+&nbsp;const1).ToString(CultureInfo.InvariantCulture),&nbsp;first&nbsp;+&nbsp;second, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"some&nbsp;const&nbsp;value".ToUpper(),&nbsp;const1); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;Expression<Func<Uri,&nbsp;bool>>&nbsp;GetPropAndMethodExpr2() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;u&nbsp;=>&nbsp;Uri.IsWellFormedUriString(u.ToString(),&nbsp;UriKind.Absolute); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;Expression<Func<Uri,&nbsp;bool>>&nbsp;GetPropAndMethodExpr1() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;arg1&nbsp;=>&nbsp;Uri.IsWellFormedUriString(arg1.ToString(),&nbsp;UriKind.Absolute); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;Expression<Func<Uri,&nbsp;UriBuilder>>&nbsp;GetMemberInitExpr2() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;isSecure&nbsp;=&nbsp;true; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;u&nbsp;=>&nbsp;new&nbsp;UriBuilder(u)&nbsp;{&nbsp;Host&nbsp;=&nbsp;string.IsNullOrEmpty(u.Host)&nbsp;?&nbsp;"abc"&nbsp;:&nbsp;"def"&nbsp;,&nbsp;Port&nbsp;=&nbsp;isSecure&nbsp;?&nbsp;443&nbsp;:&nbsp;80&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;Expression<Func<Uri,&nbsp;UriBuilder>>&nbsp;GetMemberInitExpr1() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;port&nbsp;=&nbsp;443; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;x&nbsp;=>&nbsp;new&nbsp;UriBuilder(x)&nbsp;{&nbsp;Port&nbsp;=&nbsp;port,&nbsp;Host&nbsp;=&nbsp;string.IsNullOrEmpty(x.Host)&nbsp;?&nbsp;"abc"&nbsp;:&nbsp;"def"&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;Expression<Func<Uri,&nbsp;object>>&nbsp;GetAnonymousExpr2() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;u&nbsp;=>&nbsp;new&nbsp;{&nbsp;u.Host&nbsp;,&nbsp;Port&nbsp;=&nbsp;443,&nbsp;Addr&nbsp;=&nbsp;u.AbsolutePath&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;Expression<Func<Uri,&nbsp;object>>&nbsp;GetAnonymousExpr1() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;x&nbsp;=>&nbsp;new&nbsp;{&nbsp;Port&nbsp;=&nbsp;443,&nbsp;x.Host,&nbsp;Addr&nbsp;=&nbsp;x.AbsolutePath&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;}}

哔哔one

规范的解决方案会很棒。与此同时,我创建了一个IEqualityComparer<Expression>版本。这是一个冗长的实现,所以我为它创建了一个要点。它旨在成为一个全面的抽象语法树比较器。为此,它的每一个的表达类型,包括还未被C#支持像表达式进行比较Try和Switch和Block。唯一的种类它不比较是Goto,Label,Loop并且DebugInfo由于我的限制他们的知识。您可以指定是否以及如何比较参数和lambda的名称以及如何处理ConstantExpression。它按上下文按位置跟踪参数。支持lambdas内的Lambdas和catch块变量参数。
打开App,查看更多内容
随时随地看视频慕课网APP